Skip to main content

MCP server testing and orchestration tool

Project description

๐ŸŽต Orchestra

Production-Ready MCP Server Testing and Orchestration Tool

Orchestra is a powerful CLI tool for testing MCP (Model Context Protocol) servers with declarative YAML test collections. Discover server capabilities, write comprehensive tests, and validate your MCP implementations with ease.

โœจ Key Features

  • ๐ŸŽฏ Interactive Builder โ€” new command walks you through creating collections (no YAML knowledge required!)
  • ๐Ÿ” Server Discovery โ€” inspect command reveals all available tools and their schemas
  • ๐Ÿ“ Declarative YAML โ€” Define test collections in easy-to-read YAML files
  • ๐ŸŒ Multiple Transports โ€” STDIO (local), HTTP (remote), and SSE support
  • ๐Ÿ”’ Authentication โ€” Built-in support for Bearer, API Key, and Basic auth
  • โœ… Powerful Assertions โ€” JSONPath queries, error detection, and content validation
  • โšก Rate Limit Handling โ€” Configurable delays between steps
  • ๐Ÿ“Š Detailed Reports โ€” JSON reports with run IDs, timestamps, and step-by-step results
  • ๐Ÿš€ CI/CD Ready โ€” Exit codes for pass/fail, quiet mode for automation
  • ๐Ÿ” Secure โ€” Environment variable support for secrets and API keys

๐Ÿ“ฆ Installation

# From source
pip install -e .

# Or with uv
uv pip install -e .

๐Ÿš€ Quick Start

0. Create Your First Collection (Interactive!)

New to Orchestra? Use the interactive builder:

orchestra new schemas/my_test.yaml

The wizard will guide you through:

  1. Choosing your transport type (local/remote)
  2. Configuring your server
  3. Setting up authentication (if needed)
  4. Adding example test steps

Example session:

๐ŸŽต Orchestra Collection Builder

What would you like to name this collection? My MCP Test
โœ“ Collection name: My MCP Test

How does your MCP server run?
  1. Local (STDIO) - Runs as a subprocess
  2. Remote (HTTP) - Cloud-hosted server
  3. SSE - Server-Sent Events
Choose transport type [2]: 2

Enter server URL: https://mcp.deepwiki.com/mcp
โœ“ URL: https://mcp.deepwiki.com/mcp

โœ… Collection saved to schemas/my_test.yaml

Next steps:
  1. Run orchestra inspect schemas/my_test.yaml to discover tools
  2. Edit schemas/my_test.yaml to add your test steps
  3. Run orchestra run schemas/my_test.yaml to execute tests

1. Discover Server Capabilities

Use the inspect command to discover what tools a server offers:

orchestra inspect schemas/my_server.yaml

Example output:

๐Ÿ“ก Connecting to MCP server...
   โœ… Connected to DeepWiki v2.14.3

๐Ÿ” Discovering tools...

Found 3 tool(s):

1. read_wiki_structure
   Get a list of documentation topics for a GitHub repository.

   Parameters:
   * repoName (string)
      GitHub repository in owner/repo format (e.g. "facebook/react")

   Example YAML:
   - id: call_read_wiki_structure
     type: tool_call
     tool: "read_wiki_structure"
     input:
       repoName: "facebook/react"
     save: "$"

๐Ÿ’ก Pro tip: The generated YAML from orchestra new works perfectly with inspect!

For inspection, you only need server config:

# schemas/my_server.yaml
version: 1
name: "My MCP Server"

server:
  transport: "http"
  url: "https://api.example.com/mcp"

2. Create a Test Collection (Manual Method)

If you prefer writing YAML directly:

# schemas/my_test.yaml
version: 1
name: "My MCP Test"

server:
  transport: "stdio"
  command: "npx"
  args: ["-y", "@modelcontextprotocol/server-memory"]

steps:
  - id: create_entity
    type: tool_call
    tool: "create_entities"
    input:
      entities:
        - name: "TestUser"
          entityType: "person"
          observations: ["Loves testing"]
    save: "$"
    delay_ms: 1000  # Wait 1 second before next step

  - id: verify_no_error
    type: assert
    from: "create_entity"
    check:
      op: "no_error"

  - id: verify_created
    type: assert
    from: "create_entity"
    check:
      op: "jsonpath_exists"
      path: "$.content[0].text"

3. Run the Collection

# Standard run
orchestra run schemas/my_test.yaml

# Show full JSON responses (great for debugging)
orchestra run schemas/my_test.yaml --show-responses

# Quiet mode (errors only)
orchestra run schemas/my_test.yaml --quiet

4. View the Results

๐Ÿ“„ Loading collection: schemas/my_test.yaml
   โœ… Valid collection: My MCP Test

============================================================
  Running: My MCP Test
  Server: stdio
  Steps: 3
============================================================

๐Ÿ“ก Connecting to MCP server...
   โœ… Connected to memory-server v0.6.3

โ–ถ Step: create_entity (tool_call)
  Tool: create_entities
  Input: {"entities": [{"name": "TestUser", ...}]}...
  โœ… Success
  โฑ๏ธ  Waiting 1000ms...

โ–ถ Step: verify_no_error (assert)
  Asserting on: create_entity
  Check: no_error at $
  โœ… Passed

โ–ถ Step: verify_created (assert)
  Asserting on: create_entity
  Check: jsonpath_exists at $.content[0].text
  โœ… Passed

๐Ÿ‘‹ Disconnecting...

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
  Run Report: My MCP Test
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
  Run ID:     abc123-def456
  Status:     โœ… PASSED
  Duration:   1234ms
  Started:    2026-02-14T12:00:00Z
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  Steps: 3 passed, 0 failed, 0 errors, 0 skipped
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  โœ…  tool_call - 150ms
  โœ…  assert - 2ms
  โœ…  assert - 5ms
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

๐Ÿ“ Report saved: reports/abc123-def456.json

๐Ÿ“š CLI Reference

orchestra new

Create a new test collection with an interactive wizard (perfect for beginners!).

orchestra new [output_file]

# Examples:
orchestra new schemas/my_test.yaml
orchestra new  # Defaults to schemas/my_collection.yaml

What it does:

  • Guides you through choosing transport type
  • Helps configure server connection
  • Sets up authentication if needed
  • Generates valid YAML automatically
  • Provides next steps after creation

Time to first test: ~3 minutes (75% faster than manual YAML)

See Interactive Builder Guide for detailed walkthrough.

orchestra inspect

Discover available tools and their schemas from any MCP server.

orchestra inspect <server.yaml> [OPTIONS]

Options:
  -v, --verbose    Show detailed connection info and raw schemas

Use cases:

  • Explore new MCP servers before writing tests
  • Verify correct parameter names
  • Generate example YAML snippets for tool calls

orchestra run

Run a test collection.

orchestra run <collection.yaml> [OPTIONS]

Options:
  -V, --verbose / --no-verbose  Show detailed step output (default: on)
  -q, --quiet                   Only show errors and final status
  -r, --show-responses          Show full JSON responses from tool calls
  -o, --output [text|json]      Output format (default: text)
  -R, --report-dir PATH         Directory for JSON reports (default: reports/)
  --no-report                   Don't save a JSON report

orchestra validate

Validate a collection schema without running it.

orchestra validate <collection.yaml>

orchestra info

Show Orchestra information and version.

orchestra info

๐Ÿ“– Collection Schema Reference

Server Configuration

STDIO Transport (Local Servers)

For local MCP servers that run as subprocesses:

server:
  transport: "stdio"
  command: "npx"
  args: ["-y", "@modelcontextprotocol/server-memory"]
  
  # Optional: Pass environment variables to subprocess
  env:
    API_KEY: "{{env.MY_API_KEY}}"
    DEBUG: "true"

Environment Variables for STDIO:

  • Orchestra can pass environment variables from the collection schema to the subprocess
  • Useful for servers that need API keys (e.g., Brave Search, Kaggle)
# Collection-level env vars (accessible via {{env.VAR}})
env:
  BRAVE_API_KEY: "your-key-here"

server:
  transport: "stdio"
  command: "npx"
  args: ["-y", "@modelcontextprotocol/server-brave-search"]
  # Pass to subprocess
  env:
    BRAVE_API_KEY: "{{env.BRAVE_API_KEY}}"

HTTP Transport (Remote Servers)

For remote MCP servers over HTTP (Streamable HTTP):

server:
  transport: "http"
  url: "https://mcp.deepwiki.com/mcp"

SSE Transport

For servers using Server-Sent Events:

server:
  transport: "sse"
  url: "http://localhost:3001"

With Authentication

Orchestra supports three authentication types:

Bearer Token:

server:
  transport: "http"
  url: "https://api.example.com/mcp"
  auth:
    type: "bearer"
    token: "{{env.API_TOKEN}}"

API Key:

server:
  transport: "http"
  url: "https://api.example.com/mcp"
  auth:
    type: "api_key"
    key: "{{env.API_KEY}}"

Basic Auth:

server:
  transport: "http"
  url: "https://api.example.com/mcp"
  auth:
    type: "basic"
    username: "{{env.USERNAME}}"
    password: "{{env.PASSWORD}}"

Steps

Tool Call Step

Invoke an MCP tool and optionally save the result for assertions:

- id: my_step
  type: tool_call
  tool: "tool_name"
  input:
    param1: "value"
    param2: 123
    nested:
      key: "value"
  save: "$"  # Save full response
  delay_ms: 2000  # Wait 2 seconds after this step (for rate limiting)

Rate Limiting: Use delay_ms to prevent hitting rate limits on public APIs:

steps:
  - id: search_1
    type: tool_call
    tool: "brave_web_search"
    input:
      query: "Python"
    save: "$"
    delay_ms: 2000  # Wait 2 seconds

  - id: search_2
    type: tool_call
    tool: "brave_web_search"
    input:
      query: "JavaScript"
    save: "$"
    delay_ms: 2000  # Wait 2 seconds

Assertion Step

Validate tool call results with powerful assertions:

- id: check_result
  type: assert
  from: "my_step"  # Reference a previous step
  check:
    op: "jsonpath_eq"
    path: "$.field"
    value: "expected"
  delay_ms: 0  # Optional delay after assertion

Assertion Operators

Operator Description Requires Path Requires Value Example
jsonpath_exists Check if path exists in response โœ… โŒ Path $.content[0].text exists
jsonpath_eq Check if value equals expected โœ… โœ… $.status equals "success"
jsonpath_contains Check if string/array contains value โœ… โœ… $.text contains "hello"
jsonpath_len_eq Check array length equals N โœ… โœ… $.items has exactly 5 items
jsonpath_len_gte Check array length >= N โœ… โœ… $.items has at least 3 items
jsonpath_len_lte Check array length <= N โœ… โœ… $.items has at most 10 items
is_error Check if MCP response has isError=true โŒ โŒ Response contains an error
no_error Check if MCP response has no error โŒ โŒ Response is successful

Error Detection

MCP servers can return successful JSON-RPC responses that contain tool execution errors (indicated by isError: true). Orchestra automatically detects these and provides specialized assertions:

steps:
  # Call a tool that might fail
  - id: risky_call
    type: tool_call
    tool: "some_tool"
    input:
      param: "value"
    save: "$"
  
  # Verify it succeeded
  - id: check_success
    type: assert
    from: "risky_call"
    check:
      op: "no_error"  # Fails if isError=true

  # Or test error handling
  - id: bad_call
    type: tool_call
    tool: "nonexistent_tool"
    input: {}
    save: "$"
  
  - id: expect_error
    type: assert
    from: "bad_call"
    check:
      op: "is_error"  # Passes if isError=true

Console output with error detection:

โ–ถ Step: bad_call (tool_call)
  Tool: nonexistent_tool
  โš ๏ธ  Tool returned error: Tool not found
  Response:
  {
    "content": [...],
    "isError": true
  }

โ–ถ Step: expect_error (assert)
  Check: is_error at $
  โœ… Passed

Defaults

Set default values for all steps:

defaults:
  timeout_ms: 30000  # 30 seconds (default)
  retries: 0         # No retries (default)

Environment Variables

Orchestra supports environment variable interpolation using {{env.VAR_NAME}}:

# Define at collection level
env:
  API_KEY: "my-secret-key"
  BASE_URL: "https://api.example.com"

server:
  transport: "http"
  url: "{{env.BASE_URL}}/mcp"
  auth:
    type: "api_key"
    key: "{{env.API_KEY}}"

steps:
  - id: call_with_env
    type: tool_call
    tool: "search"
    input:
      api_key: "{{env.API_KEY}}"

Environment variables are pulled from:

  1. Collection-level env block
  2. Shell environment (via os.environ)

๐Ÿงช Real-World Examples

Example 1: DeepWiki (Remote HTTP, No Auth)

Test an AI-powered documentation server:

version: 1
name: "DeepWiki Test"

server:
  transport: "http"
  url: "https://mcp.deepwiki.com/mcp"

steps:
  - id: ask_about_react
    type: tool_call
    tool: "ask_question"
    input:
      repoName: "facebook/react"
      question: "What are React hooks?"
    save: "$"
    delay_ms: 2000

  - id: check_answer
    type: assert
    from: "ask_about_react"
    check:
      op: "jsonpath_contains"
      path: "$.content[0].text"
      value: "hook"

Example 2: Brave Search (STDIO, API Key)

Test a search API with authentication:

version: 1
name: "Brave Search Test"

env:
  BRAVE_API_KEY: "your-api-key"

server:
  transport: "stdio"
  command: "npx"
  args: ["-y", "@modelcontextprotocol/server-brave-search"]
  env:
    BRAVE_API_KEY: "{{env.BRAVE_API_KEY}}"

steps:
  - id: search_python
    type: tool_call
    tool: "brave_web_search"
    input:
      query: "Python programming"
      count: 5
    save: "$"
    delay_ms: 2000  # Rate limiting

  - id: check_results
    type: assert
    from: "search_python"
    check:
      op: "jsonpath_len_gte"
      path: "$.content"
      value: 1

Example 3: MCPCalc (Remote HTTP, Calculator Service)

Test a calculator service:

version: 1
name: "MCPCalc Test"

server:
  transport: "http"
  url: "https://mcpcalc.com/api/v1/mcp"

steps:
  - id: list_calculators
    type: tool_call
    tool: "list_calculators"
    input:
      category: "math"
    save: "$"

  - id: calculate_percentage
    type: tool_call
    tool: "calculate"
    input:
      calculator: "percentage"
      inputs:
        value: 50
        percentage: 20
    save: "$"

  - id: verify_result
    type: assert
    from: "calculate_percentage"
    check:
      op: "no_error"

๐Ÿ“Š Reports

Orchestra generates detailed JSON reports for every test run:

{
  "run_id": "abc123-def456",
  "collection_name": "My Test",
  "status": "passed",
  "started_at": "2026-02-14T12:00:00Z",
  "completed_at": "2026-02-14T12:00:01Z",
  "duration_ms": 1234,
  "server": {
    "name": "memory-server",
    "version": "0.6.3"
  },
  "steps": [
    {
      "id": "create_entity",
      "type": "tool_call",
      "status": "success",
      "duration_ms": 150,
      "tool": "create_entities",
      "result": { ... }
    },
    {
      "id": "verify_created",
      "type": "assert",
      "status": "passed",
      "duration_ms": 5,
      "assertion": {
        "op": "jsonpath_exists",
        "path": "$.content[0].text"
      }
    }
  ]
}

โœ… Tested MCP Servers

Orchestra has been validated against multiple production MCP servers:

  • โœ… DeepWiki - AI-powered codebase documentation (HTTP, remote)
  • โœ… MCPCalc - Calculator service (HTTP, remote)
  • โœ… Puppeteer - Browser automation (STDIO, local)
  • โœ… Brave Search - Web search API (STDIO, API key auth)
  • โœ… Kaggle - Dataset management (STDIO, local)
  • โœ… Memory Server - Knowledge graph storage (STDIO, local)
  • โœ… Everything Server - Demo server with all MCP features (STDIO/HTTP/SSE)

๐Ÿค Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

๐Ÿ“ License

MIT

๐Ÿ™ Acknowledgments

Built on the Model Context Protocol (MCP) by Anthropic.


Made with โค๏ธ for the MCP community

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

orchestra_mcp-0.1.0.tar.gz (123.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

orchestra_mcp-0.1.0-py3-none-any.whl (51.7 kB view details)

Uploaded Python 3

File details

Details for the file orchestra_mcp-0.1.0.tar.gz.

File metadata

  • Download URL: orchestra_mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 123.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for orchestra_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c9daf5c0d0ef8064c6d8a8f9c5dbe38a448bd8ca21846a8133274c9e3cd918e9
MD5 7919374828363586e8b13831640d8592
BLAKE2b-256 55eabf4abaaf096dbb07fe38810c01a85f6ff695584574ed5d645a392529616b

See more details on using hashes here.

File details

Details for the file orchestra_mcp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: orchestra_mcp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 51.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for orchestra_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e73891bec8c3b751e28baa5f9aeb91aa21c2abba0aceadd76508830f9d9642e5
MD5 ab8237bda8e2d5c316428f754878e984
BLAKE2b-256 b064a0723cc6b74c51d1a81feccb0f13651b105f299c9626c23c5357197ad52e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page