Add MCP server
Refs https://github.com/evcc-io/evcc/issues/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 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.
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.
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 https://github.com/mark3labs/mcp-go/discussions/422. Maybe an implementation restriction. I could add an "empty response" handler but would that allow the client to actually fetch the docs?
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)?
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
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.
Creating an OpenAPI wrapper depends on https://github.com/getkin/kin-openapi/issues/1079
Tools vs. Resources: https://medium.com/@mowhobuilds/mcp-server-resources-or-tools-for-exposing-get-endpoints-162d17c4c134
No new insights, closing.