OurGroceries MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@OurGroceries MCP Add milk to my grocery list"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
OurGroceries MCP
An unofficial Model Context Protocol (MCP) server for an OurGroceries account. It relies on an unofficial API client; upstream behavior, availability, and compatibility can change without notice. Review every result and verify important changes in OurGroceries.
The Streamable HTTP server hasno built-in application authentication. Never expose it directly to the internet: anyone who can reach it can use the configured grocery account. Bind it to localhost, or put it behind an authenticated, trusted tunnel or reverse proxy that enforces authentication before forwarding requests.
Prerequisites
An OurGroceries account and its credentials.
For a source install: uv and Python 3.12 or later.
For the container option: Docker.
An MCP client for stdio or Streamable HTTP.
The server reads OURGROCERIES_EMAIL and OURGROCERIES_PASSWORD from its process environment. .env is a local template, not an automatically loaded configuration file. Keep it private and never commit it.
Related MCP server: Unofficial AnyList MCP Server
Install and configure
Source with uv
git clone https://github.com/OriginalByteMe/our-groceries-mcp.git
cd our-groceries-mcp
cp .env.example .env
# Edit .env locally; do not commit it.
uv sync --lockedSet placeholders in .env only on your machine:
OURGROCERIES_EMAIL=""
OURGROCERIES_PASSWORD=""For a shell-launched server, export the file first:
set -a
. ./.env
set +aDocker
The image starts the Streamable HTTP transport. Build it and publish the port only on localhost:
docker build -t our-groceries-mcp .
docker run --rm --env-file .env -p 127.0.0.1:8000:8000 our-groceries-mcpIts MCP endpoint is http://127.0.0.1:8000/mcp. This is an MCP endpoint, not a browser UI. If remote access is necessary, retain the localhost binding and use an authenticated trusted tunnel or reverse proxy; do not forward the port unauthenticated.
Install the agent skill
For agents that support Vercel Skills, install the repository skill:
npx skills add OriginalByteMe/our-groceries-mcp --skill our-groceries-mcpThis installs guidance, not credentials. Configure credentials locally in the MCP client or environment.
Connect an MCP client
Stdio (recommended)
After uv sync --locked, add this JSON to your client's MCP server configuration. Replace the absolute checkout path and placeholders locally; do not put real credentials in a shared config file.
{
"mcpServers": {
"our-groceries": {
"command": "uv",
"args": [
"run",
"--directory",
"/absolute/path/to/our-groceries-mcp",
"--locked",
"our-groceries-mcp"
],
"env": {
"OURGROCERIES_EMAIL": "",
"OURGROCERIES_PASSWORD": ""
}
}
}
}Stdio keeps the server local to the client process and is the safest default.
Streamable HTTP
For a source checkout, after exporting the environment variables, run:
uv run --locked our-groceries-mcp \
--transport streamable-http \
--host 127.0.0.1 \
--port 8000Connect an MCP client to http://127.0.0.1:8000/mcp. The endpoint has no HTTP authentication. Do not use 0.0.0.0 or a public host unless an authenticated trusted tunnel or reverse proxy protects every request.
Read-only smoke check
From a configured source checkout, this launches the server over stdio, initializes MCP, and calls the real read-only list_grocery_lists tool. It prints no grocery-list contents.
set -a
. ./.env
set +a
uv run --locked python - <<'PY'
import asyncio
import os
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main() -> None:
server = StdioServerParameters(
command="uv",
args=["run", "--locked", "our-groceries-mcp"],
env=dict(os.environ),
)
async with stdio_client(server) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool("list_grocery_lists", {})
if result.isError:
raise RuntimeError("list_grocery_lists failed")
print("Read-only MCP smoke check passed.")
asyncio.run(main())
PYThis contacts the live OurGroceries account. Do not run it with credentials you do not intend to use.
Tools and confirmation
List and item names are resolved by case-insensitive exact match. Resolve ambiguity with list_grocery_lists or get_items before a mutation.
Tool | Parameters | Behavior |
| none | Read available lists. |
|
| Read items in one list. |
|
| Adds immediately; it has no confirmation flag. Ask before calling it. |
|
| Returns a preview by default. Marking complete requires |
|
| Returns a preview by default. Permanent removal requires |
|
| Returns a preview by default. Moving requires |
For complete_item, remove_item, and move_item, first call with the default confirm: false, show the preview, and only call again with confirm: true after explicit user approval. add_item is an immediate write, so obtain approval before the first call.
move_item is not atomic: it adds the item to the destination, then removes it from the source. If removal fails, the item can exist in both lists. Inspect both lists before retrying so a retry does not create another duplicate.
Troubleshooting
Credentials are not configured: pass both environment variables to the server process;
.envalone is not loaded automatically.Authentication failed or requests fail: verify the account credentials and network, then retry later. This is an unofficial integration and upstream API changes can break it.
List or item not found / ambiguous: use the read tools and provide one case-insensitive exact name; rename duplicate lists or items in OurGroceries if needed.
Cannot connect over HTTP: ensure the server is running, use
/mcp(not/), and keep the host/port local unless an authenticated proxy or tunnel is in place.A move reports partial failure: check both source and destination lists manually before deciding whether to remove, move, or retry the item.
Development and testing
Install development dependencies and run the offline test suite with the lockfile:
uv sync --locked --all-groups
uv run --locked pytest -m "not live"Tests marked live require a deliberately configured live account and are excluded by default. Do not add credentials to test output, fixtures, or committed files.
Security
See SECURITY.md before enabling Streamable HTTP. In particular, direct unauthenticated internet exposure grants grocery-account access to callers.
Available Tools
6 toolsadd_itemB
Immediately add an item to a grocery list, optionally with quantity and note.
Inputs: item (required), list_name (required), note, quantity. Returns: object
complete_itemA
Preview or, with confirmation, mark a matching grocery item as complete.
Inputs: item (required), list_name (required), confirm. Returns: object
get_itemsA
Return the items in a grocery list selected by case-insensitive exact name.
Inputs: list_name (required). Returns: result
list_grocery_listsA
List grocery lists available in the configured OurGroceries account.
Inputs: no named parameters. Returns: result
move_itemA
Preview or, with confirmation, move an item between grocery lists.
Inputs: item (required), source_list (required), destination_list (required), confirm. Returns: object
remove_itemA
Preview or, with confirmation, permanently remove a matching grocery item.
Inputs: item (required), list_name (required), confirm. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 6 tools
Each tool has a clear, distinct purpose: listing lists, getting items, adding, completing, removing, and moving items. There is no overlap or ambiguity between these actions.
All tool names follow a consistent verb_noun pattern in snake_case (e.g., list_grocery_lists, add_item, complete_item). The naming is uniform and predictable.
With 6 tools, the server is well-scoped for grocery list management. Each tool addresses a distinct operation, and the count is neither too sparse nor overwhelming.
The tool set covers item-level operations (add, get, complete, remove, move) but lacks list-level create/delete operations and any way to update item details like quantity or note after creation. These are notable gaps for a grocery list management server.
Related MCP Connectors
Official Todoist MCP server. Manage tasks and projects. Hosted, no API key needed.
The **OTTTA MCP server** lets you manage your habit trackers. Add / create / update / delete groups, trackers and values. The idea behind OTTTA is to make tracking very easy. The app is simple, you create groups, in the groups you put things to track on a daily basis and then it generates graphs. You can log values to the trackers via the [OTTTA website](https://ottta.com/), via our API, our MCP of course and via the OTTTA Chrome Extension. Soon more ways will be available.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceMCP server that gives AI agents full control over grocery lists, todos, and packing lists. Your AI creates lists, adds items, checks them off, and shares with family/friends.4MIT
- AlicenseNot gradedqualityAmaintenanceMCP server that integrates with AnyList for managing shopping lists, recipes, and meal planning via natural language.35ISC
- AlicenseNot gradedqualityBmaintenanceMCP server for the Bring! shopping list API, enabling management of shopping lists via natural language.MIT
- AlicenseAqualityDmaintenanceManage grocery lists on OurGroceries.com via CLI or MCP, supporting item operations, list management, and natural-language resolution.1116 npmMIT