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.
pip install connic-composer-sdk
connic init invoice-mcp --templates=invoice
cd invoice-mcp
pip install -r requirements.txt
connic login
connic deployOpen 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.
2. Link the extractor to an MCP Server connection
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.
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.
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.
export MCP_ENDPOINT='<endpoint-url>'
export MCP_SECRET='<connection-secret>'
python mcp_invoice.pySync 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
StopIterationmeans the tool list did not containinvoice_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: truereports 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.
Link your agent to an MCP Server connection so MCP clients can call it as a tool.
Set up the MCP connection