Remove embedded OAuth implementation and flatten directory structure
Simplified the repository to have a single OAuth pattern with separate auth and MCP servers at the top level. Preserved embedded OAuth documentation as an alternative pattern.
This commit is contained in:
parent
c637d39f8d
commit
c03a9b4e77
3 changed files with 1556 additions and 15846 deletions
133
examples/README.md
Normal file
133
examples/README.md
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# MCP Server Examples
|
||||
|
||||
This directory contains example code demonstrating how to interact with the MCP server.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before running any examples, ensure:
|
||||
1. Redis is running: `docker compose up -d`
|
||||
2. Both servers are running: `npm run dev`
|
||||
3. Servers are accessible at:
|
||||
- Auth Server: http://localhost:3001
|
||||
- MCP Server: http://localhost:3232
|
||||
|
||||
## Available Examples
|
||||
|
||||
### curl-examples.sh
|
||||
|
||||
Shell script demonstrating API interactions using curl.
|
||||
|
||||
**Features:**
|
||||
- OAuth client registration
|
||||
- MCP session initialization
|
||||
- Tool calls (echo, add)
|
||||
- Resource listing and reading
|
||||
- Prompt operations
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Make executable
|
||||
chmod +x curl-examples.sh
|
||||
|
||||
# Register client (step 1)
|
||||
./curl-examples.sh
|
||||
|
||||
# After getting token (via MCP Inspector)
|
||||
./curl-examples.sh YOUR_ACCESS_TOKEN
|
||||
|
||||
# With session ID
|
||||
./curl-examples.sh YOUR_ACCESS_TOKEN YOUR_SESSION_ID
|
||||
```
|
||||
|
||||
### client.js
|
||||
|
||||
Node.js client showing programmatic interaction with the MCP server.
|
||||
|
||||
**Features:**
|
||||
- Complete OAuth flow demonstration
|
||||
- Automatic client registration
|
||||
- MCP session management
|
||||
- Tool and resource operations
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Run the example
|
||||
node client.js
|
||||
|
||||
# Or make it executable
|
||||
chmod +x client.js
|
||||
./client.js
|
||||
```
|
||||
|
||||
## Getting an Access Token
|
||||
|
||||
### Option 1: MCP Inspector (Easiest)
|
||||
|
||||
```bash
|
||||
# Launch inspector
|
||||
npx -y @modelcontextprotocol/inspector
|
||||
|
||||
# Connect to http://localhost:3232/mcp
|
||||
# Complete OAuth flow in the Auth tab
|
||||
# Copy the access token from the debug console
|
||||
```
|
||||
|
||||
### Option 2: Manual OAuth Flow
|
||||
|
||||
1. Register a client (see examples)
|
||||
2. Navigate to authorization URL
|
||||
3. Complete authentication
|
||||
4. Exchange authorization code for token
|
||||
5. Use token in API calls
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Making MCP Requests
|
||||
|
||||
All MCP requests follow this pattern:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "unique-id",
|
||||
"method": "category/action",
|
||||
"params": { /* method-specific parameters */ }
|
||||
}
|
||||
```
|
||||
|
||||
### Required Headers
|
||||
|
||||
```
|
||||
Authorization: Bearer YOUR_ACCESS_TOKEN
|
||||
Content-Type: application/json
|
||||
Mcp-Session-Id: YOUR_SESSION_ID // After initialization
|
||||
```
|
||||
|
||||
### Session Lifecycle
|
||||
|
||||
1. **Initialize**: Create a new session
|
||||
2. **Use**: Make requests with session ID
|
||||
3. **Terminate**: Optional cleanup (auto-expires after 5 min)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "401 Unauthorized"
|
||||
- Token may be expired (7-day TTL)
|
||||
- Token may be invalid
|
||||
- Get a new token via OAuth flow
|
||||
|
||||
### "Session not found"
|
||||
- Session expired (5-minute TTL)
|
||||
- Re-initialize with the same token
|
||||
|
||||
### "Cannot connect"
|
||||
- Ensure servers are running: `npm run dev`
|
||||
- Check Redis is running: `docker compose ps`
|
||||
- Verify URLs are correct
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [MCP Protocol Documentation](https://modelcontextprotocol.io)
|
||||
- [OAuth Flow Documentation](../docs/oauth-flow.md)
|
||||
- [API Endpoints Reference](../docs/endpoints.md)
|
||||
- [Main README](../README.md)
|
||||
345
examples/client.js
Executable file
345
examples/client.js
Executable file
|
|
@ -0,0 +1,345 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Simple Node.js MCP Client Example
|
||||
*
|
||||
* This demonstrates how to interact with the MCP server programmatically.
|
||||
* It handles the OAuth flow and makes MCP requests.
|
||||
*
|
||||
* Prerequisites:
|
||||
* - Both servers running: npm run dev
|
||||
* - Node.js installed
|
||||
*
|
||||
* Usage:
|
||||
* node client.js
|
||||
*/
|
||||
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
const { URL } = require('url');
|
||||
const readline = require('readline');
|
||||
|
||||
// Configuration
|
||||
const AUTH_SERVER = 'http://localhost:3001';
|
||||
const MCP_SERVER = 'http://localhost:3232';
|
||||
const REDIRECT_URI = 'http://localhost:8080/callback';
|
||||
|
||||
// Colors for console output
|
||||
const colors = {
|
||||
reset: '\x1b[0m',
|
||||
bright: '\x1b[1m',
|
||||
red: '\x1b[31m',
|
||||
green: '\x1b[32m',
|
||||
yellow: '\x1b[33m',
|
||||
blue: '\x1b[34m',
|
||||
magenta: '\x1b[35m',
|
||||
cyan: '\x1b[36m'
|
||||
};
|
||||
|
||||
// Utility functions
|
||||
const log = {
|
||||
info: (msg) => console.log(`${colors.blue}ℹ${colors.reset} ${msg}`),
|
||||
success: (msg) => console.log(`${colors.green}✓${colors.reset} ${msg}`),
|
||||
error: (msg) => console.log(`${colors.red}✗${colors.reset} ${msg}`),
|
||||
section: (msg) => console.log(`\n${colors.bright}${colors.blue}=== ${msg} ===${colors.reset}`)
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple HTTP request helper
|
||||
*/
|
||||
function makeRequest(url, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const parsedUrl = new URL(url);
|
||||
const client = parsedUrl.protocol === 'https:' ? https : http;
|
||||
|
||||
const reqOptions = {
|
||||
hostname: parsedUrl.hostname,
|
||||
port: parsedUrl.port,
|
||||
path: parsedUrl.pathname + parsedUrl.search,
|
||||
method: options.method || 'GET',
|
||||
headers: options.headers || {}
|
||||
};
|
||||
|
||||
const req = client.request(reqOptions, (res) => {
|
||||
let data = '';
|
||||
res.on('data', chunk => data += chunk);
|
||||
res.on('end', () => {
|
||||
try {
|
||||
const json = JSON.parse(data);
|
||||
resolve({ status: res.statusCode, headers: res.headers, data: json });
|
||||
} catch {
|
||||
resolve({ status: res.statusCode, headers: res.headers, data });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', reject);
|
||||
|
||||
if (options.body) {
|
||||
req.write(options.body);
|
||||
}
|
||||
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 1: Register OAuth client
|
||||
*/
|
||||
async function registerClient() {
|
||||
log.section('Registering OAuth Client');
|
||||
|
||||
const response = await makeRequest(`${AUTH_SERVER}/register`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
client_name: 'node-example-client',
|
||||
redirect_uris: [REDIRECT_URI]
|
||||
})
|
||||
});
|
||||
|
||||
if (response.status === 200 || response.status === 201) {
|
||||
log.success('Client registered successfully');
|
||||
return {
|
||||
clientId: response.data.client_id,
|
||||
clientSecret: response.data.client_secret
|
||||
};
|
||||
} else {
|
||||
throw new Error(`Registration failed: ${JSON.stringify(response.data)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 2: Simple OAuth flow (manual for demonstration)
|
||||
* In production, use a proper OAuth library
|
||||
*/
|
||||
async function performOAuthFlow(clientId, clientSecret) {
|
||||
log.section('OAuth Authorization Flow');
|
||||
|
||||
log.info('For this demo, we need you to manually complete the OAuth flow.');
|
||||
log.info('In a production app, this would be automated.\n');
|
||||
|
||||
// Generate PKCE challenge (simplified for demo)
|
||||
const codeVerifier = Buffer.from(Math.random().toString()).toString('base64url');
|
||||
const codeChallenge = Buffer.from(codeVerifier).toString('base64url');
|
||||
|
||||
const authUrl = `${AUTH_SERVER}/authorize?` +
|
||||
`client_id=${clientId}&` +
|
||||
`redirect_uri=${encodeURIComponent(REDIRECT_URI)}&` +
|
||||
`response_type=code&` +
|
||||
`code_challenge=${codeChallenge}&` +
|
||||
`code_challenge_method=plain&` +
|
||||
`state=demo-state`;
|
||||
|
||||
console.log('1. Open this URL in your browser:');
|
||||
console.log(` ${colors.cyan}${authUrl}${colors.reset}\n`);
|
||||
|
||||
console.log('2. Complete the authentication flow');
|
||||
console.log('3. You\'ll be redirected to a URL like:');
|
||||
console.log(` ${REDIRECT_URI}?code=AUTHORIZATION_CODE&state=demo-state\n`);
|
||||
|
||||
// Get authorization code from user
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
return new Promise((resolve) => {
|
||||
rl.question('4. Paste the AUTHORIZATION_CODE here: ', async (code) => {
|
||||
rl.close();
|
||||
|
||||
// Exchange code for token
|
||||
log.info('Exchanging authorization code for access token...');
|
||||
|
||||
const tokenResponse = await makeRequest(`${AUTH_SERVER}/token`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: `grant_type=authorization_code&` +
|
||||
`code=${code}&` +
|
||||
`redirect_uri=${encodeURIComponent(REDIRECT_URI)}&` +
|
||||
`client_id=${clientId}&` +
|
||||
`client_secret=${clientSecret}&` +
|
||||
`code_verifier=${codeVerifier}`
|
||||
});
|
||||
|
||||
if (tokenResponse.data.access_token) {
|
||||
log.success('Access token obtained!');
|
||||
resolve(tokenResponse.data.access_token);
|
||||
} else {
|
||||
throw new Error(`Token exchange failed: ${JSON.stringify(tokenResponse.data)}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 3: Initialize MCP session
|
||||
*/
|
||||
async function initializeMCPSession(accessToken) {
|
||||
log.section('Initializing MCP Session');
|
||||
|
||||
const response = await makeRequest(`${MCP_SERVER}/mcp`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${accessToken}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
id: 'init',
|
||||
method: 'initialize',
|
||||
params: {
|
||||
protocolVersion: '2024-11-05',
|
||||
capabilities: {},
|
||||
clientInfo: {
|
||||
name: 'node-example',
|
||||
version: '1.0'
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
if (response.data.result) {
|
||||
log.success('MCP session initialized');
|
||||
// In a real implementation, extract session ID from headers
|
||||
return response.headers['mcp-session-id'] || 'demo-session-id';
|
||||
} else {
|
||||
throw new Error(`Initialization failed: ${JSON.stringify(response.data)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 4: Demonstrate MCP features
|
||||
*/
|
||||
async function demonstrateMCPFeatures(accessToken, sessionId) {
|
||||
log.section('Demonstrating MCP Features');
|
||||
|
||||
// List available tools
|
||||
log.info('Fetching available tools...');
|
||||
const toolsResponse = await makeRequest(`${MCP_SERVER}/mcp`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${accessToken}`,
|
||||
'Mcp-Session-Id': sessionId,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
id: 'list-tools',
|
||||
method: 'tools/list'
|
||||
})
|
||||
});
|
||||
|
||||
if (toolsResponse.data.result && toolsResponse.data.result.tools) {
|
||||
console.log(`Found ${toolsResponse.data.result.tools.length} tools:`);
|
||||
toolsResponse.data.result.tools.forEach(tool => {
|
||||
console.log(` - ${colors.cyan}${tool.name}${colors.reset}: ${tool.description}`);
|
||||
});
|
||||
}
|
||||
|
||||
// Call the echo tool
|
||||
log.info('\nCalling echo tool...');
|
||||
const echoResponse = await makeRequest(`${MCP_SERVER}/mcp`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${accessToken}`,
|
||||
'Mcp-Session-Id': sessionId,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
id: 'echo-1',
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: 'echo',
|
||||
arguments: {
|
||||
message: 'Hello from Node.js client!'
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
if (echoResponse.data.result) {
|
||||
console.log('Echo response:', echoResponse.data.result.content);
|
||||
}
|
||||
|
||||
// Call the add tool
|
||||
log.info('\nCalling add tool (5 + 3)...');
|
||||
const addResponse = await makeRequest(`${MCP_SERVER}/mcp`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${accessToken}`,
|
||||
'Mcp-Session-Id': sessionId,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
id: 'add-1',
|
||||
method: 'tools/call',
|
||||
params: {
|
||||
name: 'add',
|
||||
arguments: { a: 5, b: 3 }
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
if (addResponse.data.result) {
|
||||
console.log('Add result:', addResponse.data.result.content);
|
||||
}
|
||||
|
||||
// List resources
|
||||
log.info('\nFetching available resources...');
|
||||
const resourcesResponse = await makeRequest(`${MCP_SERVER}/mcp`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${accessToken}`,
|
||||
'Mcp-Session-Id': sessionId,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
id: 'list-resources',
|
||||
method: 'resources/list'
|
||||
})
|
||||
});
|
||||
|
||||
if (resourcesResponse.data.result && resourcesResponse.data.result.resources) {
|
||||
console.log(`Found ${resourcesResponse.data.result.resources.length} resources (showing first 5):`);
|
||||
resourcesResponse.data.result.resources.slice(0, 5).forEach(resource => {
|
||||
console.log(` - ${colors.cyan}${resource.uri}${colors.reset}: ${resource.name}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function
|
||||
*/
|
||||
async function main() {
|
||||
console.log(`${colors.bright}${colors.blue}MCP Node.js Client Example${colors.reset}`);
|
||||
console.log('==========================\n');
|
||||
|
||||
try {
|
||||
// Step 1: Register client
|
||||
const { clientId, clientSecret } = await registerClient();
|
||||
console.log(`Client ID: ${clientId}`);
|
||||
console.log(`Client Secret: ${clientSecret}\n`);
|
||||
|
||||
// Step 2: OAuth flow
|
||||
const accessToken = await performOAuthFlow(clientId, clientSecret);
|
||||
|
||||
// Step 3: Initialize MCP session
|
||||
const sessionId = await initializeMCPSession(accessToken);
|
||||
|
||||
// Step 4: Demonstrate features
|
||||
await demonstrateMCPFeatures(accessToken, sessionId);
|
||||
|
||||
log.success('\nExample completed successfully!');
|
||||
|
||||
} catch (error) {
|
||||
log.error(`Error: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the example
|
||||
main();
|
||||
339
examples/curl-examples.sh
Executable file
339
examples/curl-examples.sh
Executable file
|
|
@ -0,0 +1,339 @@
|
|||
#!/bin/bash
|
||||
|
||||
# =============================================================================
|
||||
# MCP Server API Examples using curl
|
||||
# =============================================================================
|
||||
#
|
||||
# This script demonstrates how to interact with the MCP server using curl.
|
||||
# Before running, ensure both servers are running: npm run dev
|
||||
#
|
||||
# Usage: ./curl-examples.sh [access_token]
|
||||
# =============================================================================
|
||||
|
||||
# Configuration
|
||||
AUTH_SERVER="http://localhost:3001"
|
||||
MCP_SERVER="http://localhost:3232"
|
||||
CLIENT_NAME="curl-example-client"
|
||||
REDIRECT_URI="http://localhost:3000/callback"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# =============================================================================
|
||||
# Helper Functions
|
||||
# =============================================================================
|
||||
|
||||
print_section() {
|
||||
echo -e "\n${BLUE}=== $1 ===${NC}"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}✓ $1${NC}"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}✗ $1${NC}"
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e "${YELLOW}ℹ $1${NC}"
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# OAuth Client Registration
|
||||
# =============================================================================
|
||||
|
||||
register_client() {
|
||||
print_section "Registering OAuth Client"
|
||||
|
||||
RESPONSE=$(curl -s -X POST "$AUTH_SERVER/register" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"client_name\": \"$CLIENT_NAME\",
|
||||
\"redirect_uris\": [\"$REDIRECT_URI\"]
|
||||
}")
|
||||
|
||||
CLIENT_ID=$(echo "$RESPONSE" | grep -o '"client_id":"[^"]*' | cut -d'"' -f4)
|
||||
CLIENT_SECRET=$(echo "$RESPONSE" | grep -o '"client_secret":"[^"]*' | cut -d'"' -f4)
|
||||
|
||||
if [ -n "$CLIENT_ID" ]; then
|
||||
print_success "Client registered successfully"
|
||||
echo "Client ID: $CLIENT_ID"
|
||||
echo "Client Secret: $CLIENT_SECRET"
|
||||
echo
|
||||
echo "Save these credentials - you'll need them for the OAuth flow"
|
||||
else
|
||||
print_error "Failed to register client"
|
||||
echo "Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# MCP Session Initialization
|
||||
# =============================================================================
|
||||
|
||||
initialize_session() {
|
||||
local ACCESS_TOKEN=$1
|
||||
|
||||
print_section "Initializing MCP Session"
|
||||
|
||||
if [ -z "$ACCESS_TOKEN" ]; then
|
||||
print_error "Access token required"
|
||||
print_info "Get a token using MCP Inspector or implement OAuth flow"
|
||||
return 1
|
||||
fi
|
||||
|
||||
RESPONSE=$(curl -s -X POST "$MCP_SERVER/mcp" \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "init",
|
||||
"method": "initialize",
|
||||
"params": {
|
||||
"protocolVersion": "2024-11-05",
|
||||
"capabilities": {},
|
||||
"clientInfo": {
|
||||
"name": "curl-example",
|
||||
"version": "1.0"
|
||||
}
|
||||
}
|
||||
}')
|
||||
|
||||
# Extract session ID from response headers (would need -i flag)
|
||||
# For demonstration, we'll parse from response
|
||||
echo "Response: $RESPONSE"
|
||||
|
||||
# Check for error
|
||||
if echo "$RESPONSE" | grep -q "error"; then
|
||||
print_error "Failed to initialize session"
|
||||
return 1
|
||||
else
|
||||
print_success "Session initialized"
|
||||
print_info "Save the Mcp-Session-Id header for subsequent requests"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# MCP Tools Examples
|
||||
# =============================================================================
|
||||
|
||||
list_tools() {
|
||||
local ACCESS_TOKEN=$1
|
||||
local SESSION_ID=$2
|
||||
|
||||
print_section "Listing Available Tools"
|
||||
|
||||
curl -s -X POST "$MCP_SERVER/mcp" \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Mcp-Session-Id: $SESSION_ID" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "list-tools",
|
||||
"method": "tools/list"
|
||||
}' | python3 -m json.tool
|
||||
}
|
||||
|
||||
call_echo_tool() {
|
||||
local ACCESS_TOKEN=$1
|
||||
local SESSION_ID=$2
|
||||
local MESSAGE=${3:-"Hello from curl!"}
|
||||
|
||||
print_section "Calling Echo Tool"
|
||||
|
||||
curl -s -X POST "$MCP_SERVER/mcp" \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Mcp-Session-Id: $SESSION_ID" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"jsonrpc\": \"2.0\",
|
||||
\"id\": \"echo-1\",
|
||||
\"method\": \"tools/call\",
|
||||
\"params\": {
|
||||
\"name\": \"echo\",
|
||||
\"arguments\": {
|
||||
\"message\": \"$MESSAGE\"
|
||||
}
|
||||
}
|
||||
}" | python3 -m json.tool
|
||||
}
|
||||
|
||||
call_add_tool() {
|
||||
local ACCESS_TOKEN=$1
|
||||
local SESSION_ID=$2
|
||||
local A=${3:-5}
|
||||
local B=${4:-3}
|
||||
|
||||
print_section "Calling Add Tool"
|
||||
|
||||
curl -s -X POST "$MCP_SERVER/mcp" \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Mcp-Session-Id: $SESSION_ID" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"jsonrpc\": \"2.0\",
|
||||
\"id\": \"add-1\",
|
||||
\"method\": \"tools/call\",
|
||||
\"params\": {
|
||||
\"name\": \"add\",
|
||||
\"arguments\": {
|
||||
\"a\": $A,
|
||||
\"b\": $B
|
||||
}
|
||||
}
|
||||
}" | python3 -m json.tool
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# MCP Resources Examples
|
||||
# =============================================================================
|
||||
|
||||
list_resources() {
|
||||
local ACCESS_TOKEN=$1
|
||||
local SESSION_ID=$2
|
||||
|
||||
print_section "Listing Resources (First Page)"
|
||||
|
||||
curl -s -X POST "$MCP_SERVER/mcp" \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Mcp-Session-Id: $SESSION_ID" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "list-resources",
|
||||
"method": "resources/list"
|
||||
}' | python3 -m json.tool
|
||||
}
|
||||
|
||||
read_resource() {
|
||||
local ACCESS_TOKEN=$1
|
||||
local SESSION_ID=$2
|
||||
local RESOURCE_URI=${3:-"example://resource/1"}
|
||||
|
||||
print_section "Reading Resource: $RESOURCE_URI"
|
||||
|
||||
curl -s -X POST "$MCP_SERVER/mcp" \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Mcp-Session-Id: $SESSION_ID" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"jsonrpc\": \"2.0\",
|
||||
\"id\": \"read-resource\",
|
||||
\"method\": \"resources/read\",
|
||||
\"params\": {
|
||||
\"uri\": \"$RESOURCE_URI\"
|
||||
}
|
||||
}" | python3 -m json.tool
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# MCP Prompts Examples
|
||||
# =============================================================================
|
||||
|
||||
list_prompts() {
|
||||
local ACCESS_TOKEN=$1
|
||||
local SESSION_ID=$2
|
||||
|
||||
print_section "Listing Available Prompts"
|
||||
|
||||
curl -s -X POST "$MCP_SERVER/mcp" \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Mcp-Session-Id: $SESSION_ID" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "list-prompts",
|
||||
"method": "prompts/list"
|
||||
}' | python3 -m json.tool
|
||||
}
|
||||
|
||||
get_prompt() {
|
||||
local ACCESS_TOKEN=$1
|
||||
local SESSION_ID=$2
|
||||
local PROMPT_NAME=${3:-"simple_prompt"}
|
||||
|
||||
print_section "Getting Prompt: $PROMPT_NAME"
|
||||
|
||||
curl -s -X POST "$MCP_SERVER/mcp" \
|
||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
||||
-H "Mcp-Session-Id: $SESSION_ID" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"jsonrpc\": \"2.0\",
|
||||
\"id\": \"get-prompt\",
|
||||
\"method\": \"prompts/get\",
|
||||
\"params\": {
|
||||
\"name\": \"$PROMPT_NAME\"
|
||||
}
|
||||
}" | python3 -m json.tool
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Main Script
|
||||
# =============================================================================
|
||||
|
||||
main() {
|
||||
echo -e "${BLUE}MCP Server API Examples${NC}"
|
||||
echo "================================="
|
||||
|
||||
# Check if access token is provided
|
||||
ACCESS_TOKEN=$1
|
||||
SESSION_ID=$2
|
||||
|
||||
if [ -z "$ACCESS_TOKEN" ]; then
|
||||
print_info "No access token provided"
|
||||
print_info "Usage: $0 <access_token> [session_id]"
|
||||
echo
|
||||
print_section "Step 1: Register OAuth Client"
|
||||
register_client
|
||||
echo
|
||||
print_info "To continue, you need to:"
|
||||
print_info "1. Complete OAuth flow to get an access token"
|
||||
print_info "2. Run: $0 <your_access_token>"
|
||||
print_info ""
|
||||
print_info "Use MCP Inspector for easy OAuth flow:"
|
||||
print_info "npx -y @modelcontextprotocol/inspector"
|
||||
print_info "Connect to: http://localhost:3232/mcp"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# If we have a token, demonstrate API calls
|
||||
if [ -z "$SESSION_ID" ]; then
|
||||
initialize_session "$ACCESS_TOKEN"
|
||||
print_info "Rerun with: $0 $ACCESS_TOKEN <session_id>"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Demonstrate various MCP features
|
||||
list_tools "$ACCESS_TOKEN" "$SESSION_ID"
|
||||
echo
|
||||
|
||||
call_echo_tool "$ACCESS_TOKEN" "$SESSION_ID" "Hello, MCP!"
|
||||
echo
|
||||
|
||||
call_add_tool "$ACCESS_TOKEN" "$SESSION_ID" 10 25
|
||||
echo
|
||||
|
||||
list_resources "$ACCESS_TOKEN" "$SESSION_ID"
|
||||
echo
|
||||
|
||||
read_resource "$ACCESS_TOKEN" "$SESSION_ID" "example://resource/1"
|
||||
echo
|
||||
|
||||
list_prompts "$ACCESS_TOKEN" "$SESSION_ID"
|
||||
echo
|
||||
|
||||
get_prompt "$ACCESS_TOKEN" "$SESSION_ID" "simple_prompt"
|
||||
|
||||
print_success "Examples completed!"
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
Loading…
Reference in a new issue