Samuel Thomas commited on
Commit
ac57eb2
Β·
1 Parent(s): 8f7165e
Files changed (3) hide show
  1. .gitignore +290 -0
  2. app.py +129 -4
  3. requirements.txt +16 -0
.gitignore ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # poetry
98
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
+ #poetry.lock
103
+
104
+ # pdm
105
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106
+ #pdm.lock
107
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108
+ # in version control.
109
+ # https://pdm.fming.dev/#use-with-ide
110
+ .pdm.toml
111
+
112
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113
+ __pypackages__/
114
+
115
+ # Celery stuff
116
+ celerybeat-schedule
117
+ celerybeat.pid
118
+
119
+ # SageMath parsed files
120
+ *.sage.py
121
+
122
+ # Environments
123
+ .env
124
+ .venv
125
+ env/
126
+ venv/
127
+ ENV/
128
+ env.bak/
129
+ venv.bak/
130
+
131
+ # Spyder project settings
132
+ .spyderproject
133
+ .spyproject
134
+
135
+ # Rope project settings
136
+ .ropeproject
137
+
138
+ # mkdocs documentation
139
+ /site
140
+
141
+ # mypy
142
+ .mypy_cache/
143
+ .dmypy.json
144
+ dmypy.json
145
+
146
+ # Pyre type checker
147
+ .pyre/
148
+
149
+ # pytype static type analyzer
150
+ .pytype/
151
+
152
+ # Cython debug symbols
153
+ cython_debug/
154
+
155
+ # PyCharm
156
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157
+ # be added to the global gitignore or merged into this project gitignore. For a PyCharm
158
+ # project, it is also recommended to add the following directories to the gitignore:
159
+ # .idea/
160
+ .idea/
161
+ *.iws
162
+ *.iml
163
+ *.ipr
164
+
165
+ # Visual Studio Code
166
+ .vscode/
167
+ *.code-workspace
168
+
169
+ # macOS
170
+ .DS_Store
171
+ .AppleDouble
172
+ .LSOverride
173
+
174
+ # Icon must end with two \r
175
+ Icon
176
+
177
+ # Thumbnails
178
+ ._*
179
+
180
+ # Files that might appear in the root of a volume
181
+ .DocumentRevisions-V100
182
+ .fseventsd
183
+ .Spotlight-V100
184
+ .TemporaryItems
185
+ .Trashes
186
+ .VolumeIcon.icns
187
+ .com.apple.timemachine.donotpresent
188
+
189
+ # Directories potentially created on remote AFP share
190
+ .AppleDB
191
+ .AppleDesktop
192
+ Network Trash Folder
193
+ Temporary Items
194
+ .apdisk
195
+
196
+ # Windows
197
+ Thumbs.db
198
+ Thumbs.db:encryptable
199
+ ehthumbs.db
200
+ ehthumbs_vista.db
201
+ *.tmp
202
+ *.temp
203
+
204
+ # Dump file
205
+ *.stackdump
206
+
207
+ # Folder config file
208
+ [Dd]esktop.ini
209
+
210
+ # Recycle Bin used on file shares
211
+ $RECYCLE.BIN/
212
+
213
+ # Windows Installer files
214
+ *.cab
215
+ *.msi
216
+ *.msix
217
+ *.msm
218
+ *.msp
219
+
220
+ # Windows shortcuts
221
+ *.lnk
222
+
223
+ # Linux
224
+ *~
225
+
226
+ # temporary files which can be created if a process still has a handle open of a deleted file
227
+ .fuse_hidden*
228
+
229
+ # KDE directory preferences
230
+ .directory
231
+
232
+ # Linux trash folder which might appear on any partition or disk
233
+ .Trash-*
234
+
235
+ # .nfs files are created when an open file is removed but is still being accessed
236
+ .nfs*
237
+
238
+ # Gradio specific
239
+ gradio_cached_examples/
240
+ gradio.db
241
+ flagged/
242
+
243
+ # MCP specific
244
+ *.mcp
245
+ mcp_logs/
246
+
247
+ # Local configuration files
248
+ config.local.json
249
+ settings.local.json
250
+ .env.local
251
+
252
+ # Log files
253
+ *.log
254
+ logs/
255
+
256
+ # Temporary files
257
+ tmp/
258
+ temp/
259
+ *.swp
260
+ *.swo
261
+ *~
262
+
263
+ # IDE files
264
+ .sublime-project
265
+ .sublime-workspace
266
+
267
+ # Node.js (if using any npm packages)
268
+ node_modules/
269
+ npm-debug.log*
270
+ yarn-debug.log*
271
+ yarn-error.log*
272
+
273
+ # Screenshots and test outputs
274
+ screenshots/
275
+ test_outputs/
276
+ *.png
277
+ *.jpg
278
+ *.jpeg
279
+ *.gif
280
+ *.pdf
281
+
282
+ # API keys and secrets
283
+ .secrets
284
+ secrets.json
285
+ api_keys.txt
286
+
287
+ # Database files
288
+ *.db
289
+ *.sqlite
290
+ *.sqlite3
app.py CHANGED
@@ -1,7 +1,132 @@
1
  import gradio as gr
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
- demo.launch()
 
1
  import gradio as gr
2
 
3
+ def letter_counter(word: str, letter: str) -> int:
4
+ """
5
+ Count the number of occurrences of a letter in a word or text.
6
+
7
+ Args:
8
+ word (str): The input text to search through
9
+ letter (str): The letter to search for
10
+
11
+ Returns:
12
+ int: The number of times the letter appears in the text
13
+ """
14
+ if not word or not letter:
15
+ return 0
16
+
17
+ word = word.lower()
18
+ letter = letter.lower()
19
+ count = word.count(letter)
20
+ return count
21
+
22
+ def word_stats(text: str) -> dict:
23
+ """
24
+ Get comprehensive statistics about a text.
25
+
26
+ Args:
27
+ text (str): The input text to analyze
28
+
29
+ Returns:
30
+ dict: Statistics including word count, character count, etc.
31
+ """
32
+ if not text:
33
+ return {"words": 0, "characters": 0, "letters": 0, "sentences": 0}
34
+
35
+ words = len(text.split())
36
+ characters = len(text)
37
+ letters = sum(1 for c in text if c.isalpha())
38
+ sentences = text.count('.') + text.count('!') + text.count('?')
39
+
40
+ return {
41
+ "words": words,
42
+ "characters": characters,
43
+ "letters": letters,
44
+ "sentences": sentences
45
+ }
46
+
47
+ # Create a standard Gradio interface with multiple tabs
48
+ with gr.Blocks(title="Text Analysis MCP Server") as demo:
49
+ gr.Markdown("# Text Analysis Tools")
50
+ gr.Markdown("This server provides text analysis functions via both web interface and MCP.")
51
+
52
+ with gr.Tab("Letter Counter"):
53
+ with gr.Row():
54
+ text_input = gr.Textbox(
55
+ label="Enter text",
56
+ placeholder="Type your text here...",
57
+ lines=3
58
+ )
59
+ letter_input = gr.Textbox(
60
+ label="Enter letter to count",
61
+ placeholder="e.g., 'a'",
62
+ max_lines=1
63
+ )
64
+
65
+ count_output = gr.Number(label="Letter count")
66
+ count_btn = gr.Button("Count Letters", variant="primary")
67
+
68
+ count_btn.click(
69
+ fn=letter_counter,
70
+ inputs=[text_input, letter_input],
71
+ outputs=count_output
72
+ )
73
+
74
+ with gr.Tab("Text Statistics"):
75
+ stats_text_input = gr.Textbox(
76
+ label="Enter text to analyze",
77
+ placeholder="Type your text here...",
78
+ lines=5
79
+ )
80
+ stats_output = gr.JSON(label="Text Statistics")
81
+ stats_btn = gr.Button("Analyze Text", variant="primary")
82
+
83
+ stats_btn.click(
84
+ fn=word_stats,
85
+ inputs=stats_text_input,
86
+ outputs=stats_output
87
+ )
88
+
89
+ with gr.Tab("MCP Info"):
90
+ gr.Markdown("""
91
+ ## MCP Server Information
92
+
93
+ This server is running as an MCP (Model Context Protocol) server.
94
+
95
+ **MCP Endpoint**: `http://127.0.0.1:7860/gradio_api/mcp/sse`
96
+
97
+ **Available Functions**:
98
+ - `letter_counter`: Count occurrences of a letter in text
99
+ - `word_stats`: Get comprehensive text statistics
100
+
101
+ **Usage with MCP Client**:
102
+ ```json
103
+ {
104
+ "model": "your-model",
105
+ "provider": "your-provider",
106
+ "servers": [
107
+ {
108
+ "type": "sse",
109
+ "config": {
110
+ "url": "http://127.0.0.1:7860/gradio_api/mcp/sse"
111
+ }
112
+ }
113
+ ]
114
+ }
115
+ ```
116
+ """)
117
+
118
+ # Launch both the Gradio web interface and the MCP server
119
+ if __name__ == "__main__":
120
+ print("πŸš€ Starting Text Analysis Server...")
121
+ print("πŸ“Š Gradio Interface: http://127.0.0.1:7860")
122
+ print("πŸ”Œ MCP Server: http://127.0.0.1:7860/gradio_api/mcp/sse")
123
+ print("πŸ’‘ Use the Gradio interface to test functions")
124
+ print("πŸ€– Use the MCP endpoint with tiny-agents or other MCP clients")
125
+
126
+ demo.launch(
127
+ mcp_server=True,
128
+ server_name="127.0.0.1",
129
+ server_port=7860,
130
+ show_api=True
131
+ )
132
 
 
 
requirements.txt ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Core dependencies for Gradio MCP Server
2
+ gradio>=4.44.0
3
+
4
+ # Optional: For better performance and additional features
5
+ # uvicorn>=0.24.0 # ASGI server for production deployment
6
+ # fastapi>=0.104.0 # Web framework (used by Gradio internally)
7
+
8
+ # Optional: For development and testing
9
+ # pytest>=7.4.0 # Testing framework
10
+ # black>=23.0.0 # Code formatting
11
+ # flake8>=6.0.0 # Code linting
12
+
13
+ # Optional: For enhanced text processing
14
+ # nltk>=3.8.0 # Natural language processing
15
+ # spacy>=3.7.0 # Advanced NLP
16
+ # textstat>=0.7.0 # Text readability statistics