Deprecated: Function get_magic_quotes_gpc() is deprecated in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 99

Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 619

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1169

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176
8000 GitHub - rcarmo/umcp: A micro MCP server for stdio only (asyncio and synchronous)
Nothing Special   »   [go: up one dir, main page]

Skip to content

rcarmo/umcp

Β 
Β 

Repository files navigation

🐚 MicroMCP

This is a lightweight, zero-overhead implementation of Model Context Protocol (MCP) in pure Python inspired by the original bash implementation by Muthukumaran Navaneethakrishnan.

Why? I found the idea of using the simplest possible implementation of MCP in a shell script fascinating, but I wanted to see how it would look in Python with true introspection capabilities.


πŸ“‹ Features

  • βœ… Full JSON-RPC 2.0 protocol over stdio
  • βœ… Complete MCP protocol implementation
  • βœ… Dynamic tool discovery via function naming convention
  • βœ… Complete introspection of function signatures
  • βœ… Easy to extend with custom tools
  • βœ… Prompt templates for reusable, structured interactions

πŸ”§ Requirements

  • Python 3

πŸš€ Quick Start

  1. Clone the repo
git clone https://github.com/rcarmo/umcp
  1. Try it out
echo '{"jsonrpc": "2.0", "method": "tools/call", "params": {"name": "get_movies"}, "id": 1}' | python ./movie_server.py

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ MCP Host    β”‚         β”‚ MCP Server    β”‚
β”‚ (AI System) │◄──────► β”‚ (myserver.py) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ stdio   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                      β–Ό                    β–Ό                    β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚ Protocol Layer β”‚  β”‚ Business Logic β”‚  β”‚ Prompt Templates   β”‚
              β”‚ (umcp.py)      β”‚  β”‚(tool_* methods)β”‚  β”‚ (prompt_* methods) β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚                    β”‚
                      β–Ό                    β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚ Introspection β”‚    β”‚ External      β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚ Services/APIs β”‚
                                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”Œ Examples

This implementation includes two simple example servers that demonstrate how to use the MCP protocol, one for a movie booking system and another for a calculator.

Both are supplied in synchronous and asynchronous versions, showcasing how to implement tools and introspection.


πŸ“ Prompt Templates (prompts/list & prompts/get)

In addition to tool discovery, the servers expose reusable prompt templates using a simple naming convention:

  • Any method named prompt_<name> is treated as a prompt definition.
  • The method docstring becomes the prompt description (first line as summary, rest as detail).
  • Its signature is introspected and converted into a JSON Schema input definition (same mechanism as tools).
  • Optional categories can be embedded in the docstring to help clients filter prompts.

Categories Syntax

You can declare categories in the docstring using any of the following forms (case–insensitive):

Category: review
Categories: code, quality
[category: explanation]
[categories: summarization, docs]

All collected category tokens are lower‑cased, de‑duplicated, and returned as a list.

Return Value Semantics

When the host calls prompts/get with arguments, the underlying prompt_<name> method is invoked. Its return value is normalized into a messages array as follows:

Return Type Interpretation
str Wrapped as a single user message ({"role": "user", "content": {"type": "text", "text": ...}})
list of message dicts Used as-is if each item has role and content
dict containing a messages list That list is used directly
Any other object JSON-serialized into a single user message

If the host omits arguments, only the prompt description (and categories) are returnedβ€”no invocation occurs. This keeps lightweight discovery cheap.

Example: Defining Prompts

class MyServer(MCPServer):
        def prompt_code_review(self, filename: str, issues: int = 0) -> str:
                """Generate a focused code review instruction.\nCategories: code, review"""
                return (
                        f"Please review '{filename}'. Assume ~{issues} pre-identified issues. "
                        "List key problems and actionable improvements concisely." 
                )

        def prompt_summary(self, topic: str, bullets: int = 5):
                """Return a structured summarization dialogue.\n[categories: summary, documentation]"""
                return [
                        {"role": "system", "content": {"type": "text", "text": "You are a precise technical summarizer."}},
                        {"role": "user", "content": {"type": "text", "text": f"Summarize '{topic}' in {bullets} bullet points."}},
                ]

Listing Prompts

{"jsonrpc": "2.0", "id": 1, "method": "prompts/list"}

Example (truncated) response:

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
        "prompts": [
            {
                "name": "code_review",
                "description": "Generate a focused code review instruction.",
                "inputSchema": {"type": "object", "properties": {"filename": {"type": "string"}, "issues": {"type": "integer"}}, "required": ["filename"]},
                "categories": ["code", "review"]
            }
        ]
    }
}

Getting (Invoking) a Prompt

{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "prompts/get",
    "params": {"name": "code_review", "arguments": {"filename": "main.py", "issues": 3}}
}

Example response payload (messages shortened):

{
    "jsonrpc": "2.0",
    "id": 2,
    "result": {
        "description": "Generate a focused code review instruction.",
        "categories": ["code", "review"],
        "messages": [
            {"role": "user", "content": {"type": "text", "text": "Please review 'main.py'..."}}
        ]
    }
}

Async Prompt Support

In the async server (AsyncMCPServer), prompt methods may themselves be async def. The dispatcher awaits them transparently; mixed sync/async prompt definitions are supported.

Testing & Examples

See:

  • tests/test_prompts.py – sync prompt behaviors
  • tests/test_async_prompts.py – async + mixed return forms

These illustrate categories, description-only retrieval, and multi-message templates.

Design Rationale

Prompts mirror tools for discoverability but return message scaffolds instead of β€œtool results”. This enables clients (e.g., Copilot Chat) to:

  • Offer pre-built structured prompt options
  • Dynamically parameterize prompt templates via introspected schemas
  • Reduce boilerplate in higher-level orchestrators


�️ Using with VS Code & GitHub Copilot

  1. Update VS Code settings.json
"mcp": {
    "servers": {
        "my-weather-server": {
            "type": "stdio",
            "command": "/path/to/your/server.py",
            "args": [],
            "env": {
                "MCP_API_KEY": "anything_you_need"
            }
        }
    }
}
  1. Use with GitHub Copilot Chat
/mcp my-weather-server get weather for New York

🚫 Limitations

  • No concurrency/parallel processing in synchronous version
  • No streaming responses
  • Not designed for high throughput

For AI assistants and local tool execution, these aren't blocking issues.


πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

About

A micro MCP server for stdio only (asyncio and synchronous)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%
0