first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:52:23 +03:00
commit 880f412e2c
2662 changed files with 866266 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
# Error Test MCP Server
MCP STDIO server optimized for testing error scenarios and edge cases.
## Tools
- **malformed_json** - Returns malformed JSON (truncated, invalid escapes, unclosed brackets, mixed types)
- **timeout_tool** - Hangs for specified duration to test timeout handling
- **intermittent_fail** - Randomly fails based on fail_rate to test retry logic
- **network_error** - Simulates network errors (connection refused, timeout, DNS failure, SSL errors)
- **large_payload** - Returns very large payloads to test size limits
- **partial_response** - Returns incomplete responses to test handling
- **invalid_content_type** - Returns content with mismatched type declaration
## Usage
```bash
# Install dependencies
npm install
# Build
npm run build
# Run
node dist/index.js
```
## Integration Testing
This server is designed to test error handling in Bifrost's MCP integration via STDIO transport.
### Example Tool Calls
```typescript
// Test malformed JSON
{
"name": "malformed_json",
"arguments": {
"id": "test-1",
"json_type": "truncated"
}
}
// Test timeout
{
"name": "timeout_tool",
"arguments": {
"id": "test-2",
"timeout_ms": 3000
}
}
// Test intermittent failures
{
"name": "intermittent_fail",
"arguments": {
"id": "test-3",
"fail_rate": 0.7
}
}
// Test large payloads
{
"name": "large_payload",
"arguments": {
"id": "test-4",
"size_kb": 500
}
}
```

View File

@@ -0,0 +1,17 @@
module github.com/maximhq/bifrost/examples/mcps/error-test-server
go 1.26.2
require github.com/mark3labs/mcp-go v0.43.2
require (
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/invopop/jsonschema v0.13.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@@ -0,0 +1,39 @@
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mark3labs/mcp-go v0.43.2 h1:21PUSlWWiSbUPQwXIJ5WKlETixpFpq+WBpbMGDSVy/I=
github.com/mark3labs/mcp-go v0.43.2/go.mod h1:YnJfOL382MIWDx1kMY+2zsRHU/q78dBg9aFb8W6Thdw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -0,0 +1,279 @@
package main
import (
"context"
"encoding/json"
"fmt"
"math/rand"
"os"
"time"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
func main() {
// Seed random number generator
rand.Seed(time.Now().UnixNano())
// Create MCP server
s := server.NewMCPServer(
"error-test-server",
"1.0.0",
server.WithToolCapabilities(true),
)
// Register all tools
registerTimeoutAfterTool(s)
registerReturnMalformedJSONTool(s)
registerReturnErrorTool(s)
registerIntermittentFailTool(s)
registerMemoryIntensiveTool(s)
// Start STDIO server
if err := server.ServeStdio(s); err != nil {
fmt.Fprintf(os.Stderr, "Server error: %v\n", err)
os.Exit(1)
}
}
// ============================================================================
// TOOL 1: timeout_after
// ============================================================================
func registerTimeoutAfterTool(s *server.MCPServer) {
tool := mcp.NewTool("timeout_after",
mcp.WithDescription("Simulates a timeout by delaying for specified seconds"),
mcp.WithNumber("seconds",
mcp.Required(),
mcp.Description("Number of seconds to wait before responding"),
),
)
s.AddTool(tool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
var args struct {
Seconds float64 `json:"seconds"`
}
// Get arguments using the proper method
argsInterface := request.GetArguments()
// Marshal and unmarshal to convert to our struct
argsBytes, err := json.Marshal(argsInterface)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil
}
if err := json.Unmarshal(argsBytes, &args); err != nil {
return mcp.NewToolResultError(fmt.Sprintf("Invalid arguments: %v", err)), nil
}
duration := time.Duration(args.Seconds * float64(time.Second))
// Use context-aware sleep
select {
case <-time.After(duration):
response := map[string]interface{}{
"delayed_seconds": args.Seconds,
"message": fmt.Sprintf("Delayed for %.2f seconds", args.Seconds),
}
jsonResult, _ := json.Marshal(response)
return mcp.NewToolResultText(string(jsonResult)), nil
case <-ctx.Done():
return mcp.NewToolResultError("Operation cancelled or timed out"), nil
}
})
}
// ============================================================================
// TOOL 2: return_malformed_json
// ============================================================================
func registerReturnMalformedJSONTool(s *server.MCPServer) {
tool := mcp.NewTool("return_malformed_json",
mcp.WithDescription("Returns intentionally malformed JSON to test error handling"),
)
s.AddTool(tool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
// Return deliberately broken JSON
// Note: This will be wrapped in the MCP protocol, so the MCP layer should handle it
// But the content itself is invalid JSON
malformedJSON := `{"key": "value", "broken": }`
return mcp.NewToolResultText(malformedJSON), nil
})
}
// ============================================================================
// TOOL 3: return_error
// ============================================================================
func registerReturnErrorTool(s *server.MCPServer) {
tool := mcp.NewTool("return_error",
mcp.WithDescription("Returns an error with specified type"),
mcp.WithString("error_type",
mcp.Required(),
mcp.Description("Type of error to return"),
mcp.Enum("validation", "runtime", "network", "timeout", "permission"),
),
)
s.AddTool(tool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
var args struct {
ErrorType string `json:"error_type"`
}
// Get arguments using the proper method
argsInterface := request.GetArguments()
// Marshal and unmarshal to convert to our struct
argsBytes, err := json.Marshal(argsInterface)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil
}
if err := json.Unmarshal(argsBytes, &args); err != nil {
return mcp.NewToolResultError(fmt.Sprintf("Invalid arguments: %v", err)), nil
}
var errorMessage string
switch args.ErrorType {
case "validation":
errorMessage = "Validation Error: Invalid input parameters provided"
case "runtime":
errorMessage = "Runtime Error: Unexpected condition occurred during execution"
case "network":
errorMessage = "Network Error: Failed to connect to remote service"
case "timeout":
errorMessage = "Timeout Error: Operation exceeded maximum allowed time"
case "permission":
errorMessage = "Permission Error: Insufficient privileges to perform operation"
default:
errorMessage = fmt.Sprintf("Unknown error type: %s", args.ErrorType)
}
return mcp.NewToolResultError(errorMessage), nil
})
}
// ============================================================================
// TOOL 4: intermittent_fail
// ============================================================================
func registerIntermittentFailTool(s *server.MCPServer) {
tool := mcp.NewTool("intermittent_fail",
mcp.WithDescription("Fails randomly based on specified fail rate percentage (0-100)"),
mcp.WithNumber("fail_rate",
mcp.Required(),
mcp.Description("Percentage chance of failure (0-100)"),
),
)
s.AddTool(tool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
var args struct {
FailRate float64 `json:"fail_rate"`
}
// Get arguments using the proper method
argsInterface := request.GetArguments()
// Marshal and unmarshal to convert to our struct
argsBytes, err := json.Marshal(argsInterface)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil
}
if err := json.Unmarshal(argsBytes, &args); err != nil {
return mcp.NewToolResultError(fmt.Sprintf("Invalid arguments: %v", err)), nil
}
// Validate fail rate
if args.FailRate < 0 || args.FailRate > 100 {
return mcp.NewToolResultError("Fail rate must be between 0 and 100"), nil
}
// Generate random number between 0-100
randomValue := rand.Float64() * 100
if randomValue < args.FailRate {
// Fail
return mcp.NewToolResultError(fmt.Sprintf("Intermittent failure (fail_rate: %.1f%%, random: %.2f)", args.FailRate, randomValue)), nil
}
// Success
response := map[string]interface{}{
"success": true,
"fail_rate": args.FailRate,
"random": randomValue,
"message": "Operation succeeded",
}
jsonResult, _ := json.Marshal(response)
return mcp.NewToolResultText(string(jsonResult)), nil
})
}
// ============================================================================
// TOOL 5: memory_intensive
// ============================================================================
func registerMemoryIntensiveTool(s *server.MCPServer) {
tool := mcp.NewTool("memory_intensive",
mcp.WithDescription("Allocates specified amount of memory to test resource limits"),
mcp.WithNumber("size_mb",
mcp.Required(),
mcp.Description("Amount of memory to allocate in megabytes"),
),
)
s.AddTool(tool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
var args struct {
SizeMB int `json:"size_mb"`
}
// Get arguments using the proper method
argsInterface := request.GetArguments()
// Marshal and unmarshal to convert to our struct
argsBytes, err := json.Marshal(argsInterface)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil
}
if err := json.Unmarshal(argsBytes, &args); err != nil {
return mcp.NewToolResultError(fmt.Sprintf("Invalid arguments: %v", err)), nil
}
// Limit to reasonable size to prevent crashes
if args.SizeMB > 100 {
return mcp.NewToolResultError("Size limited to 100MB for safety"), nil
}
// Allocate memory (use int64 to prevent overflow)
sizeBytes := int64(args.SizeMB) * 1024 * 1024
data := make([]byte, sizeBytes)
// Fill with pattern to ensure allocation
for i := range data {
data[i] = byte(i % 256)
}
// Calculate checksum to verify allocation
var checksum uint64
for _, b := range data {
checksum += uint64(b)
}
response := map[string]interface{}{
"allocated_mb": args.SizeMB,
"allocated_bytes": sizeBytes,
"checksum": checksum,
"message": fmt.Sprintf("Successfully allocated %dMB", args.SizeMB),
}
// Clear memory before returning
data = nil
jsonResult, _ := json.Marshal(response)
return mcp.NewToolResultText(string(jsonResult)), nil
})
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,24 @@
{
"name": "error-test-server",
"version": "1.0.0",
"description": "MCP STDIO server optimized for testing error scenarios and edge cases",
"type": "module",
"bin": {
"error-test-server": "./dist/index.js"
},
"scripts": {
"build": "tsc && chmod +x dist/index.js",
"prepare": "npm run build"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.0.4",
"zod": "^3.24.1"
},
"devDependencies": {
"@types/node": "^20.10.0",
"typescript": "^5.3.3"
},
"overrides": {
"hono": "4.12.14"
}
}

View File

@@ -0,0 +1,373 @@
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
// Schemas for error test tools
const MalformedJsonSchema = z.object({
id: z.string().describe("Tool invocation ID"),
json_type: z.enum(["truncated", "invalid_escape", "unclosed_bracket", "mixed_types"]).optional(),
});
const TimeoutToolSchema = z.object({
id: z.string().describe("Tool invocation ID"),
timeout_ms: z.number().optional().describe("Timeout duration in milliseconds (default 5000)"),
});
const IntermittentFailSchema = z.object({
id: z.string().describe("Tool invocation ID"),
fail_rate: z.number().min(0).max(1).optional().describe("Probability of failure (0-1, default 0.5)"),
});
const NetworkErrorSchema = z.object({
id: z.string().describe("Tool invocation ID"),
error_type: z.enum(["connection_refused", "timeout", "dns_failure", "ssl_error"]).optional(),
});
const LargePayloadSchema = z.object({
id: z.string().describe("Tool invocation ID"),
size_kb: z.number().optional().describe("Payload size in KB (default 100)"),
});
const PartialResponseSchema = z.object({
id: z.string().describe("Tool invocation ID"),
break_at: z.enum(["start", "middle", "end"]).optional().describe("Where to break the response"),
});
const server = new Server(
{ name: "error-test-server", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "malformed_json",
description: "Returns malformed JSON to test error handling",
inputSchema: {
type: "object",
properties: {
id: { type: "string" },
json_type: {
type: "string",
enum: ["truncated", "invalid_escape", "unclosed_bracket", "mixed_types"],
description: "Type of JSON malformation",
},
},
required: ["id"],
},
},
{
name: "timeout_tool",
description: "Hangs for a specified duration to test timeouts",
inputSchema: {
type: "object",
properties: {
id: { type: "string" },
timeout_ms: {
type: "number",
description: "Timeout duration in milliseconds (default 5000)",
},
},
required: ["id"],
},
},
{
name: "intermittent_fail",
description: "Randomly fails to test retry logic",
inputSchema: {
type: "object",
properties: {
id: { type: "string" },
fail_rate: {
type: "number",
minimum: 0,
maximum: 1,
description: "Probability of failure (0-1, default 0.5)",
},
},
required: ["id"],
},
},
{
name: "network_error",
description: "Simulates various network errors",
inputSchema: {
type: "object",
properties: {
id: { type: "string" },
error_type: {
type: "string",
enum: ["connection_refused", "timeout", "dns_failure", "ssl_error"],
description: "Type of network error to simulate",
},
},
required: ["id"],
},
},
{
name: "large_payload",
description: "Returns a very large payload to test size limits",
inputSchema: {
type: "object",
properties: {
id: { type: "string" },
size_kb: {
type: "number",
description: "Payload size in KB (default 100)",
},
},
required: ["id"],
},
},
{
name: "partial_response",
description: "Returns incomplete response to test handling",
inputSchema: {
type: "object",
properties: {
id: { type: "string" },
break_at: {
type: "string",
enum: ["start", "middle", "end"],
description: "Where to break the response",
},
},
required: ["id"],
},
},
{
name: "invalid_content_type",
description: "Returns content with mismatched type declaration",
inputSchema: {
type: "object",
properties: {
id: { type: "string" },
},
required: ["id"],
},
},
],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const toolName = request.params.name;
const startTime = Date.now();
try {
switch (toolName) {
case "malformed_json": {
const args = MalformedJsonSchema.parse(request.params.arguments);
const jsonType = args.json_type || "truncated";
let malformedText: string;
switch (jsonType) {
case "truncated":
malformedText = '{"status": "success", "data": {"items": [1, 2, 3';
break;
case "invalid_escape":
malformedText = '{"status": "success", "message": "Invalid \\x escape"}';
break;
case "unclosed_bracket":
malformedText = '{"status": "success", "data": [1, 2, 3]';
break;
case "mixed_types":
malformedText = '{"status": "success", "value": NaN, "other": undefined}';
break;
default:
malformedText = '{"incomplete": true';
}
return {
content: [
{
type: "text",
text: malformedText,
},
],
};
}
case "timeout_tool": {
const args = TimeoutToolSchema.parse(request.params.arguments);
const timeoutMs = args.timeout_ms || 5000;
// Hang for the specified duration
await new Promise((resolve) => setTimeout(resolve, timeoutMs));
return {
content: [
{
type: "text",
text: JSON.stringify({
tool: "timeout_tool",
id: args.id,
timeout_ms: timeoutMs,
message: "This should have timed out",
}),
},
],
};
}
case "intermittent_fail": {
const args = IntermittentFailSchema.parse(request.params.arguments);
const failRate = args.fail_rate ?? 0.5;
// Randomly fail based on fail_rate
if (Math.random() < failRate) {
return {
content: [
{
type: "text",
text: JSON.stringify({
error: "Intermittent failure occurred",
id: args.id,
fail_rate: failRate,
}),
},
],
isError: true,
};
}
return {
content: [
{
type: "text",
text: JSON.stringify({
tool: "intermittent_fail",
id: args.id,
success: true,
fail_rate: failRate,
}),
},
],
};
}
case "network_error": {
const args = NetworkErrorSchema.parse(request.params.arguments);
const errorType = args.error_type || "connection_refused";
const errorMessages = {
connection_refused: "Connection refused: Unable to connect to remote server",
timeout: "Request timeout: Server did not respond within timeout period",
dns_failure: "DNS resolution failed: Unable to resolve hostname",
ssl_error: "SSL handshake failed: Certificate verification error",
};
return {
content: [
{
type: "text",
text: JSON.stringify({
error: errorMessages[errorType],
error_type: errorType,
id: args.id,
}),
},
],
isError: true,
};
}
case "large_payload": {
const args = LargePayloadSchema.parse(request.params.arguments);
const sizeKb = args.size_kb || 100;
// Generate a large string (approximately sizeKb KB)
const chunkSize = 1024; // 1 KB chunks
const chunks: string[] = [];
for (let i = 0; i < sizeKb; i++) {
chunks.push("x".repeat(chunkSize));
}
return {
content: [
{
type: "text",
text: JSON.stringify({
tool: "large_payload",
id: args.id,
size_kb: sizeKb,
payload: chunks.join(""),
message: `Generated ${sizeKb}KB payload`,
}),
},
],
};
}
case "partial_response": {
const args = PartialResponseSchema.parse(request.params.arguments);
const breakAt = args.break_at || "middle";
let response: string;
switch (breakAt) {
case "start":
response = '{"sta';
break;
case "middle":
response = '{"status": "success", "data": {"incomplete';
break;
case "end":
response = '{"status": "success", "data": {"complete": true}, "message": "Almost done"';
break;
}
return {
content: [
{
type: "text",
text: response,
},
],
};
}
case "invalid_content_type": {
const args = z.object({ id: z.string() }).parse(request.params.arguments);
// Return a response that claims to be JSON but isn't properly formatted
return {
content: [
{
type: "text",
text: "This is not valid JSON content but the server says it is",
},
],
};
}
default:
throw new Error(`Unknown tool: ${toolName}`);
}
} catch (error) {
return {
content: [
{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Error Test MCP Server running on stdio");
}
main().catch((error) => {
console.error("Fatal error:", error);
process.exit(1);
});

View File

@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}