Skip to main content
Connic
Back to BlogTutorial

Expose the Invoice Processor Template as an MCP Tool

Deploy Connic's invoice template as an MCP tool, discover it from Python, send invoice text, and check the extracted fields with a complete client example.

September 11, 202610 min readAuthor: Connic Engineering

Connic can publish the existing Invoice Processor template as an MCP tool. A client sends invoice text, the agent extracts fields and checks the arithmetic with Python tools, and the connection returns the result. The setup uses the template's existing agent files and a managed MCP Server connection.

Start with the agent the template already provides

The Invoice Processor template in Connic Awesome Agents includes three agents. invoice-extractor reads invoice text and returns fields such as vendor, currency, line items, and total. It uses Python calculator tools and an invoice output schema. invoice-validator checks the extracted arithmetic deterministically. invoice-pipeline runs both in sequence and returns the validator's final summary.

This walkthrough publishes invoice-extractor so the caller receives the extracted invoice fields. Connic hosts the MCP endpoint and maps the tool call to the deployed agent. The Python code below is a client used to inspect and call that endpoint. The MCP server and client explainer covers the protocol roles in more detail.

1. Deploy the invoice template

Use Python 3.10 or later in an activated virtual environment. Create a Connic project without a connected Git repository for this CLI deployment. The project needs credit for agent execution as well as the template's model calls. Run the following commands from a directory where invoice-mcp does not already exist.

connic login opens the Connic dashboard in the browser. Create a project API key there, copy the displayed login token, and paste it into the terminal prompt. The token contains the project ID and API key. If the browser does not open, follow the URL printed by the CLI.

terminal
pip install connic-composer-sdk
connic init invoice-mcp --templates=invoice
cd invoice-mcp
pip install -r requirements.txt
connic login
connic deploy

Open the deployment URL printed by the CLI and wait for the deployment to succeed and become active. Command completion means the deployment was submitted. With the default settings, Connic runs the included tests before activation. If a build or test fails, inspect the deployment logs before proceeding. The quickstart covers both CLI and Git deployment; projects with Git connected use their configured deployment branch.

Open invoice-extractor in the environment with the active deployment. In its connection diagram, choose Add inbound connector, then Create New Connector and MCP Server. Select Sync (Wait for Result), keep authentication enabled, and create the connection. Link only the extractor for this example.

Copy the endpoint URL and secret from the connection details. Use the complete generated URL, including its connection ID. This secret authenticates calls to this connection; the project login token from step 1 is a separate credential. The endpoint accepts an Authorization: Bearer header or X-Connic-Secret. Configuration details are in the MCP Server documentation.

A native or server-side MCP client must support remote HTTP connections and a custom authentication header to use this endpoint. The connection uses a shared secret and provides no OAuth sign-in flow. Browser requests carrying an Origin header are rejected. The terminal client below exercises the connection directly.

3. Discover invoice_extractor from Python

Save the following code as mcp_invoice.py. It uses Python's standard library and the 2026-07-28 protocol supported by Connic. Each request includes protocol metadata and matching HTTP headers. This diagnostic script reads the JSON responses Connic returns for these methods in that revision; a general MCP client must also handle other response forms. The Streamable HTTP specification defines the transport requirements.

mcp_invoice.py
import json
import os
from urllib.error import HTTPError
from urllib.request import Request, urlopen

endpoint = os.environ["MCP_ENDPOINT"]
secret = os.environ["MCP_SECRET"]
protocol_version = "2026-07-28"


def request(method, params, request_id):
    params = {
        **params,
        "_meta": {
            "io.modelcontextprotocol/protocolVersion": protocol_version,
            "io.modelcontextprotocol/clientInfo": {
                "name": "invoice-tutorial",
                "version": "1.0.0",
            },
            "io.modelcontextprotocol/clientCapabilities": {},
        },
    }
    headers = {
        "Authorization": f"Bearer {secret}",
        "Content-Type": "application/json",
        "Accept": "application/json, text/event-stream",
        "MCP-Protocol-Version": protocol_version,
        "Mcp-Method": method,
    }
    if method == "tools/call":
        headers["Mcp-Name"] = params["name"]
    body = {"jsonrpc": "2.0", "id": request_id,
            "method": method, "params": params}
    http_request = Request(endpoint, json.dumps(body).encode(), headers)
    try:
        with urlopen(http_request, timeout=310) as response:
            data = json.load(response)
    except HTTPError as error:
        raise RuntimeError(
            f"HTTP {error.code}: {error.read().decode()}"
        ) from error
    if "error" in data:
        raise RuntimeError(data["error"])
    result = data["result"]
    if result.get("isError"):
        raise RuntimeError(result["content"])
    return result


tools = request("tools/list", {}, 1)["tools"]
tool = next(tool for tool in tools if tool["name"] == "invoice_extractor")
print(json.dumps(tool, indent=2))

The MCP tool methods separate discovery from execution: tools/list describes the available tools; tools/call invokes one. Connic converts the agent name invoice-extractor to invoice_extractor. The printed tool definition contains an inputSchema with a required string message and an optional object payload.

This tool schema describes the request sent to the agent. The template's invoice schema controls the agent's output inside Connic; the MCP connection does not advertise it as an MCP outputSchema or return a structuredContent field.

4. Call the tool with a sample invoice

Append this code to the same file. It sends a fictional invoice as payload.text. Connic merges the payload fields into the agent input, so the extractor receives message and text at the top level.

mcp_invoice.py (continued)
invoice_text = (
    "Example Supplier, invoice INV-001. "
    "Issued 2026-09-11, due 2026-09-25. "
    "Consulting: 2 hours at EUR 100, line total EUR 200. "
    "Subtotal EUR 200. Tax 19%: EUR 38. Total EUR 238."
)
result = request("tools/call", {
    "name": "invoice_extractor",
    "arguments": {
        "message": "Extract the invoice fields and check the arithmetic.",
        "payload": {"text": invoice_text},
    },
}, 2)

invoice = json.loads(result["content"][0]["text"])
print(json.dumps(invoice, indent=2))
expected = {"currency": "EUR", "subtotal": 200, "tax_amount": 38, "total": 238}
for field, value in expected.items():
    if invoice.get(field) != value:
        raise ValueError(f"Unexpected {field}: {invoice.get(field)!r}")

Replace both placeholders with the connection details from step 2 and run the file in a shell that supports export. Keep the secret in the local environment; exclude it from source files and shared transcripts.

terminal
export MCP_ENDPOINT='<endpoint-url>'
export MCP_SECRET='<connection-secret>'
python mcp_invoice.py

Sync returns after the agent finishes, with up to five minutes of waiting at the connection. The extractor's own 45-second timeout still applies. The helper checks HTTP errors, JSON-RPC errors, and result.isError before returning content. For a successful extraction, result.content[0].text contains the invoice JSON as a string, which the second code block decodes.

5. Check the extracted fields and inspect the run

The sample has a known calculation: two hours at EUR 100 produce a EUR 200 subtotal; 19% tax adds EUR 38, for a EUR 238 total. The script checks those numeric fields and the currency. Also compare the printed vendor, invoice number, dates, and line items with the input. The expected values come from the sample's arithmetic. A model performs the extraction, so check its output even when the tool call succeeds.

Open the agent run in the dashboard to inspect the received input, calculator calls, output, and any errors. The runs and traces guide explains the view. If the sample fails, the failing layer narrows the next check:

  • An HTTP 401 points to the connection secret or authentication header.
  • A missing tool or StopIteration means the tool list did not contain invoice_extractor. Check the endpoint, linked agent, and agent name.
  • A protocol error calls for checking the protocol version, method headers, and request metadata together.
  • isError: true reports failed execution or a timeout. Inspect the returned error and the agent trace.
  • A JSON decoding error or an unexpected invoice field requires inspecting the returned text and extractor output.

Use the pipeline when the caller needs a validation summary

Link invoice-pipeline to publish a second tool named invoice_pipeline. That sequence extracts fields and then runs the deterministic validator. Its final result is the validation summary, so adapt the client parsing and checks to that result. The validator reports arithmetic discrepancies; it does not verify that a supplier or invoice is genuine.

Keep Sync when the caller needs the result in the same request. Inbound mode returns a run ID while the agent works in the background. For an application that submits invoice text over ordinary HTTP, the invoice webhook walkthrough uses the same extractor through an HTTP connection.

Expose your agent as an MCP tool

Link your agent to an MCP Server connection so MCP clients can call it as a tool.

Set up the MCP connection

Frequently Asked Questions

Connic's MCP Server connection publishes the linked agent as a tool and provides its endpoint and authentication secret. The template supplies the agent, calculator tools, output schema, middleware, and tests. The Python example in this tutorial is a client that calls the managed endpoint.

The mcp_servers field lets an agent consume tools from external MCP servers. To publish the invoice agent for other clients, link it to an MCP Server connection in the dashboard.

Yes. Each agent linked to the connection appears as a tool. Linking invoice-extractor and invoice-pipeline exposes invoice_extractor and invoice_pipeline. They return different results: extracted invoice fields and the pipeline's final validation summary respectively.

More from the Blog

Tutorial

How to Deploy a Python AI Agent Without Kubernetes

A Python AI agent deployed without Kubernetes using YAML, plain Python, deployment-gated tests, Git, and a managed EU runtime. Includes working code.

August 12, 202612 min read
Tutorial

How to Trigger AI Agents from Kafka Topics

Point a Connic Kafka inbound connector at a topic and every message starts an agent run. Configure the connector, link an agent, deploy, and watch runs.

July 12, 20268 min read
Tutorial

How Small Engineering Teams Can Add an AI Agent to SaaS

A practical, step-by-step path to shipping a first production AI agent with a small team: scope one job, define it in config, connect it to existing systems, and let a runtime handle the rest.

June 12, 20269 min read
Tutorial

Automated Agent Scoring: AI Agent Evaluation with LLM Judges

Automated agent scoring uses an LLM judge to grade sampled or every matching agent run against defined criteria. Track score trends and alert on regressions.

March 29, 202610 min read
Tutorial

Migrate from LangChain to Production AI Agents

A working LangChain prototype still needs to handle real traffic. Migrate existing agent code to a production-grade platform without rewriting from scratch.

March 23, 202611 min read
Tutorial

Database vs Retrieval vs Sessions: Agent Memory Compared

A comparison of Connic's Database, Retrieval, and persistent sessions, including identity, TTL, sanitized events, and runs matched to that identity.

March 4, 202612 min read
Tutorial

Hidden Costs of Self-Hosting AI Agents

We'll just deploy it on Kubernetes. Famous last words. The true cost of self-hosting AI agents versus a managed platform.

December 18, 20257 min read
Tutorial

AI Agents in SaaS Without an ML Team

Customers expect AI features even when a product team has no ML engineers. See how teams ship AI agents using skills they already have.

December 5, 20258 min read
Tutorial

AI Agent RAG Tutorial: Retrieval With Citations

Build a production RAG agent with scoped retrieval namespaces, read-only permissions, source citations, custom tool wrappers, and regression tests.

November 15, 20259 min read