Skip to content

Conversation

fswair
Copy link
Contributor

@fswair fswair commented Aug 22, 2025

Summary

As we talked before with @Kludex about loading mcp servers from an existed configuration, I made this PR to implement this. It is based on Claude config files. See: https://docs.anthropic.com/en/docs/claude-code/mcp

Changes

  • Added load_mcp_servers function to Load MCP Servers from a configuration file or configuration data.
  • Added test_load_mcp_servers test function to mcp_test.py

Using

from pydantic_ai.mcp import MCPServer, load_mcp_servers
from pydantic_ai import Agent

servers: list[MCPServer] = load_mcp_servers(
    '/path/to/mcp.json',
    stdio_options={'timeout': 50},
    server_options={'timeout': 100}
)

# servers: list[MCPServer] = load_mcp_servers(mcp_config={'mcpServers': {...}})

agent = Agent('openai:gpt-4o', toolsets=servers)

async def main():
    async with agent:
        result = await agent.run('What is the most visited country in the world?')
        print(result.output)

if __name__ == '__main__':
    import asyncio
    asyncio.run(main())

@DouweM
Copy link
Collaborator

DouweM commented Aug 25, 2025

@fswair Thanks Mert! A few high level notes:

  • Can we use Pydantic BaseModels to validate the mcp.json contents, so that we can work with objects instead of dicts and Anys?
  • This could be a class method on the main MCPServer, like MCPServer.from_json(path)
  • I'd rather not have the stdio_options and server_options since we don't have a way to specify options for specific MCP servers, and we don't do any type checking on the arguments. Additional options can always be set directly on the resulting instances.

@fswair
Copy link
Contributor Author

fswair commented Aug 25, 2025

@fswair Thanks Mert! A few high level notes:

  • Can we use Pydantic BaseModels to validate the mcp.json contents, so that we can work with objects instead of dicts and Anys?
  • This could be a class method on the main MCPServer, like MCPServer.from_json(path)
  • I'd rather not have the stdio_options and server_options since we don't have a way to specify options for specific MCP servers, and we don't do any type checking on the arguments. Additional options can always be set directly on the resulting instances.

Thanks for reply. I'm gonna change validation logic with Pydantic again.

We talked before PR with Marcelo and he said there no need to add it as a member method, so i defined it as a pure function like he said. In the first implementation, it was a member method and there was BaseModel s to validate it. See https://github.com/fswair/mcploader/blob/main/mcploader%2Fmodels.py#L21

Btw, I found this more useful as a pure method, like marcelo.

@fswair
Copy link
Contributor Author

fswair commented Aug 25, 2025

Might be some parameters to pass MCPServer constructors? Example, timeout, read_timeout and max_retries pretty enough for this load mechanism. I thought: Especially, timeout parameter needed for this kind things.

I used this document to define structure: https://docs.anthropic.com/en/docs/claude-code/mcp , if this notation supports timeout and readTimeout it can be passed directly from MCP config. I'm a bit confused about this configuration standart.

@DouweM
Copy link
Collaborator

DouweM commented Aug 26, 2025

Might be some parameters to pass MCPServer constructors? Example, timeout, read_timeout and max_retries pretty enough for this load mechanism. I thought: Especially, timeout parameter needed for this kind things.

@fswair yeah that makes more sense to me, copy the arguments that make sense.

@fswair
Copy link
Contributor Author

fswair commented Aug 26, 2025

cool.

@fswair
Copy link
Contributor Author

fswair commented Aug 30, 2025

Logic changed, tests fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants