Skip to content

Commit 2b81538

Browse files
committed
docs: Add back advanced usage sections to README
Add back sections on low-level server implementation, client usage, MCP primitives and server capabilities that were previously removed.
1 parent fbce3d4 commit 2b81538

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

README.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434
- [Examples](#examples)
3535
- [Echo Server](#echo-server)
3636
- [SQLite Explorer](#sqlite-explorer)
37+
- [Advanced Usage](#advanced-usage)
38+
- [Low-Level Server](#low-level-server)
39+
- [Writing MCP Clients](#writing-mcp-clients)
40+
- [MCP Primitives](#mcp-primitives)
41+
- [Server Capabilities](#server-capabilities)
3742
- [Documentation](#documentation)
3843
- [Contributing](#contributing)
3944
- [License](#license)
@@ -325,6 +330,144 @@ def query_data(sql: str) -> str:
325330
return f"Error: {str(e)}"
326331
```
327332

333+
## Advanced Usage
334+
335+
### Low-Level Server
336+
337+
For more control, you can use the low-level server implementation directly. This gives you full access to the protocol and allows you to customize every aspect of your server:
338+
339+
```python
340+
from mcp.server.lowlevel import Server, NotificationOptions
341+
from mcp.server.models import InitializationOptions
342+
import mcp.server.stdio
343+
import mcp.types as types
344+
345+
# Create a server instance
346+
server = Server("example-server")
347+
348+
@server.list_prompts()
349+
async def handle_list_prompts() -> list[types.Prompt]:
350+
return [
351+
types.Prompt(
352+
name="example-prompt",
353+
description="An example prompt template",
354+
arguments=[
355+
types.PromptArgument(
356+
name="arg1",
357+
description="Example argument",
358+
required=True
359+
)
360+
]
361+
)
362+
]
363+
364+
@server.get_prompt()
365+
async def handle_get_prompt(
366+
name: str,
367+
arguments: dict[str, str] | None
368+
) -> types.GetPromptResult:
369+
if name != "example-prompt":
370+
raise ValueError(f"Unknown prompt: {name}")
371+
372+
return types.GetPromptResult(
373+
description="Example prompt",
374+
messages=[
375+
types.PromptMessage(
376+
role="user",
377+
content=types.TextContent(
378+
type="text",
379+
text="Example prompt text"
380+
)
381+
)
382+
]
383+
)
384+
385+
async def run():
386+
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
387+
await server.run(
388+
read_stream,
389+
write_stream,
390+
InitializationOptions(
391+
server_name="example",
392+
server_version="0.1.0",
393+
capabilities=server.get_capabilities(
394+
notification_options=NotificationOptions(),
395+
experimental_capabilities={},
396+
)
397+
)
398+
)
399+
400+
if __name__ == "__main__":
401+
import asyncio
402+
asyncio.run(run())
403+
```
404+
405+
### Writing MCP Clients
406+
407+
The SDK provides a high-level client interface for connecting to MCP servers:
408+
409+
```python
410+
from mcp import ClientSession, StdioServerParameters
411+
from mcp.client.stdio import stdio_client
412+
413+
# Create server parameters for stdio connection
414+
server_params = StdioServerParameters(
415+
command="python", # Executable
416+
args=["example_server.py"], # Optional command line arguments
417+
env=None # Optional environment variables
418+
)
419+
420+
async def run():
421+
async with stdio_client(server_params) as (read, write):
422+
async with ClientSession(read, write) as session:
423+
# Initialize the connection
424+
await session.initialize()
425+
426+
# List available prompts
427+
prompts = await session.list_prompts()
428+
429+
# Get a prompt
430+
prompt = await session.get_prompt("example-prompt", arguments={"arg1": "value"})
431+
432+
# List available resources
433+
resources = await session.list_resources()
434+
435+
# List available tools
436+
tools = await session.list_tools()
437+
438+
# Read a resource
439+
resource = await session.read_resource("file://some/path")
440+
441+
# Call a tool
442+
result = await session.call_tool("tool-name", arguments={"arg1": "value"})
443+
444+
if __name__ == "__main__":
445+
import asyncio
446+
asyncio.run(run())
447+
```
448+
449+
### MCP Primitives
450+
451+
The MCP protocol defines three core primitives that servers can implement:
452+
453+
| Primitive | Control | Description | Example Use |
454+
|-----------|-----------------------|-----------------------------------------------------|------------------------------|
455+
| Prompts | User-controlled | Interactive templates invoked by user choice | Slash commands, menu options |
456+
| Resources | Application-controlled| Contextual data managed by the client application | File contents, API responses |
457+
| Tools | Model-controlled | Functions exposed to the LLM to take actions | API calls, data updates |
458+
459+
### Server Capabilities
460+
461+
MCP servers declare capabilities during initialization:
462+
463+
| Capability | Feature Flag | Description |
464+
|-------------|------------------------------|------------------------------------|
465+
| `prompts` | `listChanged` | Prompt template management |
466+
| `resources` | `subscribe`<br/>`listChanged`| Resource exposure and updates |
467+
| `tools` | `listChanged` | Tool discovery and execution |
468+
| `logging` | - | Server logging configuration |
469+
| `completion`| - | Argument completion suggestions |
470+
328471
## Documentation
329472

330473
- [Model Context Protocol documentation](https://modelcontextprotocol.io)

0 commit comments

Comments
 (0)