A while back I built openapi-mcp-gateway, which turns any OpenAPI spec into an MCP server. That solved the supply side. But the people who most wanted those tools, product folks, support staff, ops, were never going to install Claude Desktop and paste a server URL into a config file. They live in Slack and LINE.
The real work was putting a chat face on those tools, one a non-technical person can just talk to. Once you try it, three things stop being optional very fast.
- Per-User Auth Inside the Chat: you cannot send someone to a JSON config to complete an OAuth flow, and you certainly cannot let the whole team act as one shared service account.
- A Confirmation Before Anything Destructive: an LLM with write access to a real API will eventually try to do the wrong thing confidently.
- Replies That Render Natively: a wall of Markdown that looks fine in one client is broken in the next.
By the time all three worked, I had Conciergent.
It connects to any Model Context Protocol server, or an OpenAPI spec directly, and turns it into a Slack, LINE, or Discord bot that can actually do things. Everyone shares one bot, but in a direct message each person signs in to your tools as themselves, so the bot acts only with the permissions of whoever asked. Destructive tools pause behind an approval card, and the agent emits one structured reply that each surface renders on its own. One YAML file sets it up.
Quick Start
Install with the gateway extra and scaffold a config.
uv add "conciergent[gateway]"
uv run conciergent init # writes an annotated manifest.yml
The scaffolded manifest.yml is deep-merged over the shipped defaults, so you set only what you change. Point the agent at an MCP server, or drop in an OpenAPI spec, set your Slack, LINE, or Discord credentials as env vars, and run it.
uv run conciergent run
The fastest end-to-end path is the bundled Docker compose, which brings up Redis, Postgres, and the app together from one of the example configs.
cp examples/openapi-chat.yml manifest.yml
docker compose up
Python 3.12+. Three model providers ship in the box (OpenAI, Google Gemini, Anthropic Claude). Set agent.model to a provider:model string and export that provider's key.
Features
Three things, each shown in config.
1. Any MCP Server, or an OpenAPI Spec Directly
Most useful bots touch more than one thing. Point the agent at any MCP server URL.
# manifest.yml
agent:
model: openai:gpt-6-luna
system_prompt: |
You are a helpful assistant. Use your tools to answer the user's requests.
mcp_servers:
- http://localhost:9000/mcp
- https://another-server.example.com/mcp
And if what you have is a REST API rather than an MCP server, you do not need to run a second process for it. Conciergent embeds openapi-mcp-gateway in-process, so a spec becomes MCP tools right there.
gateway:
enabled: true
# Keeps the gateway's OAuth clients across restarts.
redis_url: ${CONCIERGENT_MESSAGES_URL:-redis://localhost:6379/0}
specs:
- name: github
spec: https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json
base_url: https://api.github.com
policy:
allow: ["pulls/*", "issues/*", "git/delete-ref"]
- name: internal
spec: ./internal-api.json
Each spec is served at /{name}/mcp and wired into the agent for you, alongside anything already in agent.mcp_servers. A spec entry takes openapi-mcp-gateway's per-server options, so a large API can use exposure.style: dynamic (the agent sees three meta-tools instead of one per endpoint), a policy that picks the operations to expose, or auth.
2. in-Chat OAuth, the Constraint That Drove the Design
This is the part that makes a chat bot different from an MCP client on your laptop. When a tool needs authorization, there is no config file to edit and no desktop app to bounce through. The user is in a Slack, LINE, or Discord DM, and the authorization has to happen right there.
So Conciergent runs the whole OAuth handoff inside the conversation. The first time a tool needs a token, the bot posts an Authorize card into the chat. The user taps it, approves, and comes back to the same DM. Conciergent stores the token and refreshes it from then on, per user. Nobody leaves the conversation, nobody shares one team-wide credential, and anyone can ask the bot to sign them out, which revokes their token.
The same handoff covers an oauth2 spec behind the embedded gateway, so each user authorizes their own upstream account before its tools run. And because the flow is time-bounded, a slow authorization expires cleanly instead of hanging the request.
Tokens persist in Postgres, so a redeploy does not sign everyone out. Chat history lives only in Redis, one week by default, along with the other transient state (approvals, the pending handoff). Nothing a user says is retained past that window.
3. an Approval Gate, and One Reply That Renders Everywhere
Two problems, one design.
Human-in-the-loop. Any tool the MCP server marks destructive pauses behind a Confirm / Cancel card before it runs. The model proposes the action, and the human commits it. A pending approval has its own TTL, so an ignored card does not sit forever holding a write open.
Surface-agnostic replies. The agent never speaks Slack, LINE, or Discord. It emits one of three shapes, and each surface renders it natively.
-
strfor plain text. -
Cardfor a header with an optional subtitle, up to six sections of text, bullets, or label and value facts, an optional hero image, a footnote, link buttons, and suggestion quick-replies. -
Carouselfor one to four option cards the user picks between.
A suggestion is the interactive primitive. Tapping one posts its prompt back to the agent as if the user had typed it. The field descriptions on these models are the agent's structured-output schema, so the model fills them in directly and the same reply object renders correctly on Slack, LINE, and Discord.
UI text (buttons, prompts, greetings) is not hardcoded either. It lives in a locale catalog, picked from each user's platform language, so the bot answers people in their own language with no per-message translation calls.
Beyond Direct Messages
Direct messages are the default, and three opt-in features reach further.
- Group Chats: a LINE group, a Slack channel, or a Discord server channel shares one history, with each message prefixed by its speaker's name. A group never runs a per-user sign-in, so it uses only tools that work without one, and a confirmation belongs to the member whose request parked it.
-
Pushes:
conciergent push <name>runs a configured prompt with no incoming message and sends the reply into a LINE chat, such as a daily digest or a reminder. Conciergent has no scheduler of its own, so cron or a Kubernetes CronJob decides when it runs. - Charts: the agent writes a Vega-Lite spec from its tool results, and the chart becomes the card's hero image.
Comparison
The question that sorts this field is not which agent has the most features, but who the bot is for. Conciergent is built for a service provider who wants to give their own users a bot on the Slack, LINE, or Discord those users already have. Most of the projects it gets compared to are built for someone else, so they make different trade-offs. Two groups come up the most.
- Personal Assistants like Hermes Agent and OpenClaw. You run one for yourself and reach it from any chat app. They do far more than Conciergent (voice, memory, self-improving skills, dozens of channels), but each install serves a single owner with a single set of credentials, so there is no notion of separate end-users.
- Self-Hosted AI Platforms like Dify, Open WebUI, and LibreChat. They overlap the most, with multi-tenant deployments, per-user OAuth, native MCP, and heavy maintenance. But your users reach them in the platform's own web app. Getting onto Slack or Discord means a relay that pipes that web-app chat into the DM, text-first, with no native cards and no per-user OAuth in the conversation.
| Conciergent | Personal assistants | Self-hosted AI platforms | |
|---|---|---|---|
| Built for | Your users | Just you | Your users |
| Surface | Their Slack / LINE / Discord | 20+ chat apps | Its own web app |
| Separate end-users | Yes | No | In web app |
| Per-user OAuth | Yes, in chat | No | Yes, in its web app |
| Native cards and carousels | Yes, per surface | Text-first | Web app only |
| Approval gate | Yes | Yes | Partial |
| MCP and OpenAPI to tools | Both | MCP only | Both |
The assistants that reach these surfaces run for a single owner, and the multi-tenant platforms stay in a web app. Neither puts a per-user bot with native replies in the chat itself.
It fits three situations in particular.
- Internal Tools for Non-Technical Teammates: support, ops, finance. They will never open an MCP config, but they will DM a bot. Point Conciergent at your internal MCP server (or spec) and they talk to it.
- Actions as the Actual User: approving a request, moving a record, closing a ticket on someone's behalf, where the upstream audit log has to show the human. The in-chat per-user OAuth handles that end to end.
- Quick API Demos: enable the gateway, drop in the spec, and you have a Slack, LINE, or Discord bot over it with no second server to run.
Closing
Conciergent is the companion to openapi-mcp-gateway. The gateway turns a REST API into MCP tools, and Conciergent gives those tools a chat face. Together they take one or more OpenAPI specs all the way to a bot your users can talk to.
Each surface is one class behind a small contract, with the runtime and agent unchanged, so a new platform does not need a rewrite. If your platform or use case is missing, open an issue with the shape of your problem. Concrete use cases drive the design more than my guesses.
- Repository: github.com/mroops0111/conciergent
- Companion Project: github.com/mroops0111/openapi-mcp-gateway

Top comments (0)