File size: 3,094 Bytes
dd325fe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import gradio as gr


@gr.mcp.tool(
    _meta={
        "openai/outputTemplate": "ui://widget/app.html",
        "openai/resultCanProduceWidget": True,
        "openai/widgetAccessible": True,
    }
)
def letter_counter(word: str, letter: str) -> int:
    """
    Count the number of letters in a word or phrase.

    Parameters:
        word (str): The word or phrase to count the letters of.
        letter (str): The letter to count the occurrences of.
    """
    return word.count(letter)


@gr.mcp.resource("ui://widget/app.html", mime_type="text/html+skybridge")
def app_html():
    visual = """
    <div id="letter-card-container"></div>
    <script>
        const container = document.getElementById('letter-card-container');

        function render() {
            const word = window.openai?.toolInput?.word || "strawberry";
            const letter = window.openai?.toolInput?.letter || "r";

            let letterHTML = '';
            for (let i = 0; i < word.length; i++) {
                const char = word[i];
                const color = char.toLowerCase() === letter.toLowerCase() ? '#b8860b' : '#000000';
                letterHTML += `<span style="color: ${color};">${char}</span>`;
            }

            container.innerHTML = `
                <div style="
                    background: linear-gradient(135deg, #f5f5dc 0%, #e8e4d0 100%);
                    background-image:
                        repeating-linear-gradient(45deg, transparent, transparent 2px, rgba(139, 121, 94, 0.03) 2px, rgba(139, 121, 94, 0.03) 4px),
                        linear-gradient(135deg, #f5f5dc 0%, #e8e4d0 100%);
                    border-radius: 16px;
                    padding: 40px;
                    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
                    max-width: 600px;
                    margin: 20px auto;
                    font-family: 'Georgia', serif;
                    text-align: center;
                ">
                    <div style="
                        font-size: 48px;
                        font-weight: bold;
                        letter-spacing: 8px;
                        line-height: 1.5;
                    ">
                        ${letterHTML}
                    </div>
                </div>
            `;
        }
        render();
        window.addEventListener("openai:set_globals", (event) => {
            if (event.detail?.globals?.toolInput) {
                render();
            }
        }, { passive: true });
    </script>
    """
    return visual


with gr.Blocks() as demo:
    with gr.Row():
        with gr.Column():
            word = gr.Textbox(label="Word")
            letter = gr.Textbox(label="Letter")
            btn = gr.Button("Count Letters")
        with gr.Column():
            count = gr.Number(label="Count")
            html = gr.Code(language="html", max_lines=20)

    btn.click(letter_counter, inputs=[word, letter], outputs=count)
    btn.click(app_html, outputs=html)

if __name__ == "__main__":
    demo.launch(mcp_server=True, share=True)