8000 cleanup · mark3labs/mcp-go@564b669 · GitHub
[go: up one dir, main page]

Skip to content

Commit 564b669

committed
cleanup
1 parent 6ac1843 commit 564b669

File tree

3 files changed

+91
-1349
lines changed

3 files changed

+91
-1349
lines changed

www/docs/pages/transports/http.mdx

Lines changed: 0 additions & 347 deletions
Original file line numberDiff line numberDiff line change
@@ -678,354 +678,7 @@ type Claims struct {
678678
}
679679
```
680680

681-
## Client Integration
682681

683-
### Go HTTP Client
684-
685-
```go
686-
package main
687-
688-
import (
689-
"context"
690-
"log"
691-
692-
"github.com/mark3labs/mcp-go/client"
693-
)
694-
695-
func main() {
696-
// Create HTTP client
697-
c := client.NewHTTPClient("http://localhost:8080/mcp")
698-
699-
// Add authentication
700-
c.SetHeader("Authorization", "Bearer your-jwt-token")
701-
702-
// Set custom headers
703-
c.SetHeader("X-API-Version", "v1")
704-
c.SetHeader("X-Client-ID", "my-app")
705-
706-
ctx := context.Background()
707-
708-
// Initialize connection
709-
if err := c.Initialize(ctx); err != nil {
710-
log.Fatal(err)
711-
}
712-
713-
// List tools
714-
tools, err := c.ListTools(ctx)
715-
if err != nil {
716-
log.Fatal(err)
717-
}
718-
719-
log.Printf("Available tools: %d", len(tools.Tools))
720-
721-
// Call tool
722-
result, err := c.CallTool(ctx, mcp.CallToolRequest{
723-
Params: mcp.CallToolRequestParams{
724-
Name: "search_users",
725-
Arguments: map[string]interface{}{
726-
"query": "john",
727-
"limit": 5,
728-
},
729-
},
730-
})
731-
if err != nil {
732-
log.Fatal(err)
733-
}
734-
735-
log.Printf("Tool result: %+v", result)
736-
}
737-
```
738-
739-
### JavaScript/Fetch Client
740-
741-
```javascript
742-
class MCPHTTPClient {
743-
constructor(baseURL, options = {}) {
744-
this.baseURL = baseURL;
745-
this.headers = {
746-
'Content-Type': 'application/json',
747-
...options.headers
748-
};
749-
this.requestId = 1;
750-
}
751-
752-
setAuthToken(token) {
753-
this.headers['Authorization'] = `Bearer ${token}`;
754-
}
755-
756-
async sendRequest(method, params = {}) {
757-
const id = this.requestId++;
758-
const request = {
759-
jsonrpc: '2.0',
760-
id,
761-
method,
762-
params
763-
};
764-
765-
const response = await fetch(`${this.baseURL}/${method.replace('/', '/')}`, {
766-
method: 'POST',
767-
headers: this.headers,
768-
body: JSON.stringify(request)
769-
});
770-
771-
if (!response.ok) {
772-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
773-
}
774-
775-
const result = await response.json();
776-
777-
if (result.error) {
778-
throw new Error(result.error.message);
779-
}
780-
781-
return result.result;
782-
}
783-
784-
async initialize() {
785-
return this.sendRequest('initialize', {
786-
protocolVersion: '2024-11-05',
787-
capabilities: { tools: {} },
788-
clientInfo: { name: 'Web Client', version: '1.0.0' }
789-
});
790-
}
791-
792-
async listTools() {
793-
return this.sendRequest('tools/list');
794-
}
795-
796-
async callTool(name, arguments) {
797-
return this.sendRequest('tools/call', { name, arguments });
798-
}
799-
800-
async listResources() {
801-
return this.sendRequest('resources/list');
802-
}
803-
804-
async readResource(uri) {
805-
return this.sendRequest('resources/read', { uri });
806-
}
807-
}
808-
809-
// Usage
810-
const client = new MCPHTTPClient('http://localhost:8080/mcp');
811-
client.setAuthToken('your-jwt-token');
812-
813-
async function main() {
814-
try {
815-
await client.initialize();
816-
817-
const tools = await client.listTools();
818-
console.log('Available tools:', tools);
819-
820-
const result = await client.callTool('search_users', {
821-
query: 'john',
822-
limit: 10
823-
});
824-
console.log('Search result:', result);
825-
826-
} catch (error) {
827-
console.error('Error:', error);
828-
}
829-
}
830-
831-
main();
832-
```
833-
834-
### cURL Examples
835-
836-
```bash
837-
# Initialize session
838-
curl -X POST http://localhost:8080/mcp/initialize \
839-
-H "Content-Type: application/json" \
840-
-H "Authorization: Bearer your-token" \
841-
-d '{
842-
"jsonrpc": "2.0",
843-
"id": 1,
844-
"method": "initialize",
845-
"params": {
846-
"protocolVersion": "2024-11-05",
847-
"capabilities": {"tools": {}},
848-
"clientInfo": {"name": "curl", "version": "1.0.0"}
849-
}
850-
}'
851-
852-
# List tools
853-
curl -X POST http://localhost:8080/mcp/tools/list \
854-
-H "Content-Type: application/json" \
855-
-H "Authorization: Bearer your-token" \
856-
-d '{
857-
"jsonrpc": "2.0",
858-
"id": 2,
859-
"method": "tools/list",
860-
"params": {}
861-
}'
862-
863-
# Call tool
864-
curl -X POST http://localhost:8080/mcp/tools/call \
865-
-H "Content-Type: application/json" \
866-
-H "Authorization: Bearer your-token" \
867-
-d '{
868-
"jsonrpc": "2.0",
869-
"id": 3,
870-
"method": "tools/call",
871-
"params": {
872-
"name": "search_users",
873-
"arguments": {
874-
"query": "john",
875-
"limit": 10
876-
}
877-
}
878-
}'
879-
880-
# Read resource
881-
curl -X POST http://localhost:8080/mcp/resources/read \
882-
-H "Content-Type: application/json" \
883-
-H "Authorization: Bearer your-token" \
884-
-d '{
885-
"jsonrpc": "2.0",
886-
"id": 4,
887-
"method": "resources/read",
888-
"params": {
889-
"uri": "users://123"
890-
}
891-
}'
892-
```
893-
894-
## Performance and Scaling
895-
896-
### Load Balancing
897-
898-
```go
899-
// Use with nginx or HAProxy
900-
upstream mcp_servers {
901-
server 127.0.0.1:8080;
902-
server 127.0.0.1:8081;
903-
server 127.0.0.1:8082;
904-
}
905-
906-
server {
907-
listen 80;
908-
server_name api.example.com;
909-
910-
location /mcp/ {
911-
proxy_pass http://mcp_servers;
912-
proxy_set_header Host $host;
913-
proxy_set_header X-Real-IP $remote_addr;
914-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
915-
proxy_set_header X-Forwarded-Proto $scheme;
916-
}
917-
}
918-
```
919-
920-
### Caching Strategies
921-
922-
```go
923-
type CacheMiddleware struct {
924-
cache map[string]cacheEntry
925-
mutex sync.RWMutex
926-
ttl time.Duration
927-
}
928-
929-
type cacheEntry struct {
930-
data *mcp.ReadResourceResult
931-
timestamp time.Time
932-
etag string
933-
}
934-
935-
func (m *CacheMiddleware) ResourceMiddleware(next server.ResourceHandler) server.ResourceHandler {
936-
return func(ctx context.Context, req mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
937-
// Check cache
938-
m.mutex.RLock()
939-
entry, exists := m.cache[req.Params.URI]
940-
m.mutex.RUnlock()
941-
942-
if exists && time.Since(entry.timestamp) < m.ttl {
943-
// Add cache headers
944-
if httpCtx := getHTTPContext(ctx); httpCtx != nil {
945-
httpCtx.Header().Set("Cache-Control", fmt.Sprintf("max-age=%d", int(m.ttl.Seconds())))
946-
httpCtx.Header().Set("ETag", entry.etag)
947-
}
948-
return entry.data, nil
949-
}
950-
951-
// Fetch fresh data
952-
result, err := next(ctx, req)
953-
if err != nil {
954-
return nil, err
955-
}
956-
957-
// Cache result
958-
etag := generateETag(result)
959-
m.mutex.Lock()
960-
m.cache[req.Params.URI] = cacheEntry{
961-
data: result,
962-
timestamp: time.Now(),
963-
etag: etag,
964-
}
965-
m.mutex.Unlock()
966-
967-
// Set cache headers
968-
if httpCtx := getHTTPContext(ctx); httpCtx != nil {
969-
httpCtx.Header().Set("Cache-Control", fmt.Sprintf("max-age=%d", int(m.ttl.Seconds())))
970-
httpCtx.Header().Set("ETag", etag)
971-
}
972-
973-
return result, nil
974-
}
975-
}
976-
```
977-
978-
### Rate Limiting
979-
980-
```go
981-
type RateLimiter struct {
982-
limiters map[string]*rate.Limiter
983-
mutex sync.RWMutex
984-
rate rate.Limit
985-
burst int
986-
}
987-
988-
func NewRateLimiter(requestsPerSecond float64, burst int) *RateLimiter {
989-
return &RateLimiter{
990-
limiters: make(map[string]*rate.Limiter),
991-
rate: rate.Limit(requestsPerSecond),
992-
burst: burst,
993-
}
994-
}
995-
996-
func (rl *RateLimiter) getLimiter(clientIP string) *rate.Limiter {
997-
rl.mutex.RLock()
998-
limiter, exists := rl.limiters[clientIP]
999-
rl.mutex.RUnlock()
1000-
1001-
if !exists {
1002-
rl.mutex.Lock()
1003-
limiter = rate.NewLimiter(rl.rate, rl.burst)
1004-
rl.limiters[clientIP] = limiter
1005-
rl.mutex.Unlock()
1006-
}
1007-
1008-
return limiter
1009-
}
1010-
1011-
func (rl *RateLimiter) Allow(clientIP string) bool {
1012-
return rl.getLimiter(clientIP).Allow()
1013-
}
1014-
1015-
// HTTP middleware
1016-
func (rl *RateLimiter) Middleware(next http.Handler) http.Handler {
1017-
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1018-
clientIP := getClientIP(r)
1019-
1020-
if !rl.Allow(clientIP) {
1021-
http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests)
1022-
return
1023-
}
1024-
1025-
next.ServeHTTP(w, r)
1026-
})
1027-
}
1028-
```
1029682

1030683
## Next Steps
1031684

0 commit comments

Comments
 (0)
0