Skip to content

Commit 036ab84

Browse files
authored
Merge pull request modelcontextprotocol#2 from modelcontextprotocol/zack-lee/specification
Added license and technical specification
2 parents 9f3e0e9 + 2d065e5 commit 036ab84

20 files changed

+4792
-71
lines changed

LICENSE.md

Lines changed: 386 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 350 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,355 @@
11
---
22
title: "Connection Management"
3-
description: "Manage MCP client connections"
3+
description: "Learn how to establish and manage MCP client connections"
44
---
55

6-
# Connection Management
6+
## Overview
77

8-
Manage MCP client connections
8+
The MCP client API provides flexible connection management options with support for different transport types. This guide covers establishing connections, handling connection events, and managing connection lifecycles.
9+
10+
## Creating a client
11+
12+
First, create an MCP client instance with your application's information.
13+
14+
<CodeGroup>
15+
```typescript TypeScript
16+
import { Client } from "@modelcontextprotocol/sdk";
17+
18+
const client = new Client({
19+
name: "my-application",
20+
version: "1.0.0"
21+
});
22+
```
23+
24+
```python Python
25+
from mcp import Client
26+
27+
client = Client(
28+
name="my-application",
29+
version="1.0.0"
30+
)
31+
```
32+
</CodeGroup>
33+
34+
## Transport types
35+
36+
MCP supports multiple transport types for different use cases. Choose the appropriate transport based on your needs.
37+
38+
### WebSocket transport
39+
40+
Use WebSocket transport for real-time bidirectional communication.
41+
42+
<CodeGroup>
43+
```typescript TypeScript
44+
import { WebSocketClientTransport } from "@modelcontextprotocol/sdk";
45+
46+
const transport = new WebSocketClientTransport(
47+
new URL("ws://localhost:3000")
48+
);
49+
50+
await client.connect(transport);
51+
```
52+
53+
```python Python
54+
from mcp.transports import WebSocketTransport
55+
56+
transport = WebSocketTransport(
57+
url="ws://localhost:3000"
58+
)
59+
60+
await client.connect(transport)
61+
```
62+
</CodeGroup>
63+
64+
### SSE transport
65+
66+
Server-Sent Events transport is suitable for scenarios where the server pushes data to the client.
67+
68+
<CodeGroup>
69+
```typescript TypeScript
70+
import { SSEClientTransport } from "@modelcontextprotocol/sdk";
71+
72+
const transport = new SSEClientTransport(
73+
new URL("http://localhost:3000/events")
74+
);
75+
76+
await client.connect(transport);
77+
```
78+
79+
```python Python
80+
from mcp.transports import SSETransport
81+
82+
transport = SSETransport(
83+
url="http://localhost:3000/events"
84+
)
85+
86+
await client.connect(transport)
87+
```
88+
</CodeGroup>
89+
90+
### Stdio transport
91+
92+
For local server processes, use the stdio transport to communicate via standard input/output.
93+
94+
<CodeGroup>
95+
```typescript TypeScript
96+
import { StdioClientTransport } from "@modelcontextprotocol/sdk";
97+
98+
const transport = new StdioClientTransport({
99+
command: "/path/to/server",
100+
args: ["--arg1", "--arg2"],
101+
env: { "KEY": "value" }
102+
});
103+
104+
await client.connect(transport);
105+
```
106+
107+
```python Python
108+
from mcp.transports import StdioTransport
109+
110+
transport = StdioTransport(
111+
command="/path/to/server",
112+
args=["--arg1", "--arg2"],
113+
env={"KEY": "value"}
114+
)
115+
116+
await client.connect(transport)
117+
```
118+
</CodeGroup>
119+
120+
## Connection lifecycle
121+
122+
### Event handling
123+
124+
Set up event handlers to manage the connection lifecycle.
125+
126+
<CodeGroup>
127+
```typescript TypeScript
128+
client.onclose = () => {
129+
console.log("Connection closed");
130+
};
131+
132+
client.onerror = (error) => {
133+
console.error("Connection error:", error);
134+
};
135+
136+
// Transport-specific events
137+
transport.onclose = () => {
138+
console.log("Transport closed");
139+
};
140+
141+
transport.onerror = (error) => {
142+
console.error("Transport error:", error);
143+
};
144+
```
145+
146+
```python Python
147+
@client.on_close
148+
async def handle_close():
149+
print("Connection closed")
150+
151+
@client.on_error
152+
async def handle_error(error):
153+
print(f"Connection error: {error}")
154+
155+
# Transport-specific events
156+
@transport.on_close
157+
async def handle_transport_close():
158+
print("Transport closed")
159+
160+
@transport.on_error
161+
async def handle_transport_error(error):
162+
print(f"Transport error: {error}")
163+
```
164+
</CodeGroup>
165+
166+
### Connection states
167+
168+
Monitor and manage connection states throughout your application's lifecycle.
169+
170+
<CodeGroup>
171+
```typescript TypeScript
172+
// Check if connected
173+
if (client.transport) {
174+
console.log("Client is connected");
175+
}
176+
177+
// Get server capabilities after connection
178+
const capabilities = client.getServerCapabilities();
179+
const serverVersion = client.getServerVersion();
180+
181+
// Clean up connection
182+
await client.close();
183+
```
184+
185+
```python Python
186+
# Check if connected
187+
if client.transport:
188+
print("Client is connected")
189+
190+
# Get server capabilities after connection
191+
capabilities = client.get_server_capabilities()
192+
server_version = client.get_server_version()
193+
194+
# Clean up connection
195+
await client.close()
196+
```
197+
</CodeGroup>
198+
199+
## Error handling
200+
201+
Implement robust error handling for connection-related issues.
202+
203+
<CodeGroup>
204+
```typescript TypeScript
205+
try {
206+
await client.connect(transport);
207+
} catch (error) {
208+
if (error.code === ErrorCode.ConnectionClosed) {
209+
// Handle connection closure
210+
} else if (error.code === ErrorCode.InvalidRequest) {
211+
// Handle invalid request
212+
} else {
213+
// Handle other errors
214+
}
215+
}
216+
```
217+
218+
```python Python
219+
try:
220+
await client.connect(transport)
221+
except ConnectionClosedError:
222+
# Handle connection closure
223+
pass
224+
except InvalidRequestError:
225+
# Handle invalid request
226+
pass
227+
except McpError as e:
228+
# Handle other errors
229+
pass
230+
```
231+
</CodeGroup>
232+
233+
## Best practices
234+
235+
<CardGroup cols={2}>
236+
<Card title="Connection management" icon="plug">
237+
Always close connections when they're no longer needed to free up resources
238+
</Card>
239+
<Card title="Error handling" icon="shield-check">
240+
Implement comprehensive error handling for all connection states
241+
</Card>
242+
<Card title="Event handling" icon="bell">
243+
Set up appropriate event handlers before establishing connections
244+
</Card>
245+
<Card title="Resource cleanup" icon="broom">
246+
Use try/finally blocks to ensure proper cleanup of resources
247+
</Card>
248+
</CardGroup>
249+
250+
## Connection examples
251+
252+
Here are some common connection patterns:
253+
254+
<AccordionGroup>
255+
<Accordion title="Basic connection with retry">
256+
<CodeGroup>
257+
```typescript TypeScript
258+
async function connectWithRetry(
259+
client: Client,
260+
transport: Transport,
261+
maxAttempts = 3
262+
) {
263+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
264+
try {
265+
await client.connect(transport);
266+
return;
267+
} catch (error) {
268+
if (attempt === maxAttempts) throw error;
269+
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
270+
}
271+
}
272+
}
273+
```
274+
275+
```python Python
276+
async def connect_with_retry(
277+
client: Client,
278+
transport: Transport,
279+
max_attempts: int = 3
280+
):
281+
for attempt in range(max_attempts):
282+
try:
283+
await client.connect(transport)
284+
return
285+
except Exception as e:
286+
if attempt == max_attempts - 1:
287+
raise
288+
await asyncio.sleep(attempt + 1)
289+
```
290+
</CodeGroup>
291+
</Accordion>
292+
293+
<Accordion title="Connection with timeout">
294+
<CodeGroup>
295+
```typescript TypeScript
296+
async function connectWithTimeout(
297+
client: Client,
298+
transport: Transport,
299+
timeoutMs = 5000
300+
) {
301+
const timeoutPromise = new Promise((_, reject) => {
302+
setTimeout(() => reject(new Error("Connection timeout")), timeoutMs);
303+
});
304+
305+
await Promise.race([
306+
client.connect(transport),
307+
timeoutPromise
308+
]);
309+
}
310+
```
311+
312+
```python Python
313+
async def connect_with_timeout(
314+
client: Client,
315+
transport: Transport,
316+
timeout: float = 5.0
317+
):
318+
async with asyncio.timeout(timeout):
319+
await client.connect(transport)
320+
```
321+
</CodeGroup>
322+
</Accordion>
323+
</AccordionGroup>
324+
325+
## Troubleshooting
326+
327+
<AccordionGroup>
328+
<Accordion title="Connection refused">
329+
- Verify the server is running and accessible
330+
- Check if the port is correct and available
331+
- Ensure firewalls aren't blocking the connection
332+
</Accordion>
333+
334+
<Accordion title="Authentication failures">
335+
- Verify credentials if required
336+
- Check if environment variables are properly set
337+
- Ensure transport configuration is correct
338+
</Accordion>
339+
340+
<Accordion title="Connection drops">
341+
- Implement reconnection logic
342+
- Check network stability
343+
- Monitor server health
344+
</Accordion>
345+
</AccordionGroup>
346+
347+
## Transport selection guide
348+
349+
Choose the appropriate transport based on your use case:
350+
351+
| Transport | Use Case | Advantages | Considerations |
352+
|-----------|----------|------------|----------------|
353+
| WebSocket | Real-time bidirectional | Full-duplex, low latency | Requires WebSocket server |
354+
| SSE | Server push updates | Simple, firewall-friendly | One-way server push |
355+
| Stdio | Local process communication | Simple, reliable | Limited to local processes |

0 commit comments

Comments
 (0)