8000 Add MCP server by andig · Pull Request #21936 · evcc-io/evcc · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add MCP server #21936

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft

Add MCP server #21936

wants to merge 4 commits into from

Conversation

andig
Copy link
Member
@andig andig commented Jun 19, 2025

Refs #21921

Questions:

  • what's the right way to add external HTTP resources (we don't want to proxy these, so no handler)
  • ist number-loadpoints a resource or a tool? is it correct for a tool to return text in the case or do we need stronger typing?
  • do we even need number-loadpoints or is it sufficient to just return all loadpoints for the AI to figure out their total number?

@andig andig added the infrastructure Basic functionality label Jun 19, 2025
Copy link
Contributor
@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @andig - I've reviewed your changes - here's some feedback:

  • Move the demonstration files (test.go and handler_loadpoint_status.go) into an examples/ folder or remove them—production code shouldn’t include standalone example mains.
  • Consolidate URI extraction helpers (extractID, extractNumericID, extractUserIDFromURI, etc.) into a single utility to avoid duplicated logic across the codebase.
  • Uncomment and configure the CORS and compression middleware for the /mcp route so clients can access the MCP API reliably and with optimal performance.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Move the demonstration files (`test.go` and `handler_loadpoint_status.go`) into an `examples/` folder or remove them—production code shouldn’t include standalone example mains.
- Consolidate URI extraction helpers (`extractID`, `extractNumericID`, `extractUserIDFromURI`, etc.) into a single utility to avoid duplicated logic across the codebase.
- Uncomment and configure the CORS and compression middleware for the `/mcp` route so clients can access the MCP API reliably and with optimal performance.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@nickels
Copy link
nickels commented Jun 19, 2025

@andig I'm working on further implementing based on what you started. Once i've got it together I'll push, can I push to this branch? Not sure..

On the questions:

Tools vs Resources: A Practical Philosophy

The implementation demonstrates a clear conceptual model that goes beyond mere categorization. What strikes me is how the distinction naturally emerges from the domain itself:

Resources create a navigable information architecture:

// Hierarchical, discoverable state representation
"loadpoints://{loadpoint_id}"    // Individual charging point states
"vehicles://list"                // Vehicle fleet overview
"metrics://current"              // Real-time energy flows
"battery://status"               // Storage system telemetry

Tools orchestrate state transitions with clear intent:

// Explicit, purposeful actions
"start-charging"     // Initiates energy transfer
"set-charge-mode"    // Defines optimization strategy
"set-charge-plan"    // Temporal coordination (80% by 7am)
"set-priority"       // Resource allocation logic

This separation is not only about safety or API design, it also creates a language for energy management that both humans and AI can reason about effectively.

External Resources: Trusting the Web

The external documentation resource reveals an elegant truth about distributed systems:

s.AddResource(
    mcp.NewResource(
        "https://docs.evcc.io",
        "docs",
        mcp.WithResourceDescription("evcc documentation"),
    ),
    nil, // TODO no handler needed
)

That nil handler isn't a TODO to be fixed—it's a feature. By declaring external resources without proxying them, we're making a profound architectural statement: the MCP server is a curator, not a gatekeeper. It says "here's valuable context you should know about" without inserting itself into the data flow.

Each external resource enriches the AI's context without coupling evcc to external services other than those already implemented to have evcc function as it does.

@naltatis
Copy link
Member

Architecture: I'm not convinced that it is a good idea to connect the MCP adapter directly to our core and open another full-control channel to the outside. I'd rather see it as an adapter/bridge that provides more fine grain and use-case specific interaction built ontop of our existing external interface (e.g. REST API). This way we can e.g. reuse authentication and make testing this a lot easier.

@naltatis naltatis marked this pull request as draft June 20, 2025 09:30
@naltatis naltatis added the experimental Experimental feature label Jun 20, 2025
@andig
Copy link
Member Author
andig commented Jun 20, 2025

Once i've got it together I'll push, can I push to this branch? Not sure..

@nickels you'll need to target this branch in a new PR. Really looking forward to it!

For each addition: can we add prompts that should be supported now? I've tried adding the MCP to Claude Desktop (and change my plan) but I can't get Claude to actually produce answers.

Tools vs Resources: A Practical Philosophy
Resources create a navigable information architecture:

Total number of loadpoints would really be a resource then? Or rather- wo we even need that or should we simply return all loadpoints? Is the representation of loadpoints as (slice of) JSON even helpful?

External Resources: Trusting the Web
That nil handler isn't a TODO to be fixed—it's a feature

I would agree if it didn't create a panic, see mark3labs/mcp-go#422. Maybe an implementation restriction. I could add an "empty response" handler but would that allow the client to actually fetch the docs?

@andig
Copy link
Member Author
andig commented Jun 20, 2025

Architecture: I'm not convinced that it is a good idea to connect the MCP adapter directly to our core and open another full-control channel to the outside. I'd rather see it as an adapter/bridge that provides more fine grain and use-case specific interaction built ontop of our existing external interface (e.g. REST API). This way we can e.g. reuse authentication and make testing this a lot easier.

@naltatis @nickels I'd treat this as first experiment, not design. I've seem other posts turning a OpenAPI spec into a consumable MCP server. If agents had the ability to consume OpenAPI we might skip any of that- but would need to provide an OpenAPI spec. Might be helpful anyway but establishes a new contract.

For time being- should we continue as-is (or prototype an additional approach)?

@naltatis
Copy link
Member
naltatis commented Jun 20, 2025

but would need to provide an OpenAPI spec

We already have that: https://docs.evcc.io/docs/integrations/rest-api

Only thing missing there is an extensive documentation for the /api/state response payload. I also think this endpoint is the most complicated part for a LLM to interact with since we currently provide very little documentation on the meaning of the different fields. Sometimes it's obvious by name (loadpoints[0].chargePower) but not always.

But we already have plans to auto-generate a JSON schema with explanations from the newly introduced TypeScript structure (see here).

It still might be a good idea to add another, more use-case focused abstraction ontop of the /api/state endpoint that's easier to consume: "Whats the charging state of vehicle B?"

\cc @Maschga

@andig
Copy link
Member Author
andig commented Jun 20, 2025

It still might be a good idea to add another, more use-case focused abstraction ontop of the /api/state endpoint that's easier to consume: "Whats the charging state of vehicle B?"

PR answers this for a loadpoint ;). However imho its up to the AI to find out via vehicle-loadpoint relation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
experimental Experimental feature infrastructure Basic functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0