fix(mcp): use JSON-compatible invitation dates (#6814)
This commit is contained in:
1 parent
61d3fd5f08
commit
3358b6337f
7 files changed
+25
-5
No files matched your search
@@ -27,6 +27,12 @@ session cookie.
|
||||
API keys do not expire automatically and act as the user that created them. Every request uses that user's group and
|
||||
resource permissions.
|
||||
|
||||
## Invitation dates
|
||||
|
||||
`POST /api/invites` and the tRPC `invite.createInvite` procedure accept `expirationDate` as an ISO 8601 timestamp with a
|
||||
timezone, for example `2026-12-01T18:00:00Z`. Homarr validates the timestamp and stores it as a date. tRPC callers should
|
||||
send the ISO string rather than a JavaScript `Date` object.
|
||||
|
||||
## Health probes
|
||||
|
||||
The liveness endpoint does not require authentication:
|
||||
|
||||
@@ -55,6 +55,9 @@ the catalog by namespace, tool name, or description; matching categories expand
|
||||
MCP supports API keys and OAuth 2.1 with PKCE. API keys are simpler for direct client configuration; OAuth is available
|
||||
for clients that support dynamic authorization.
|
||||
|
||||
Copy the complete generated API key, including both parts and the dot: `<id>.<token>`. Sending only the ID or token
|
||||
returns `invalid_token`. Keep the full key private when sharing client configuration or diagnostics.
|
||||
|
||||
When Homarr is behind a reverse proxy that does not preserve the public host and protocol, set `BASE_URL` to the exact
|
||||
public origin, for example `https://homarr.example.com`. Do not include a path. OAuth clients discover the authorization
|
||||
server and protected resource through Homarr's `/.well-known/` routes.
|
||||
@@ -79,12 +82,20 @@ curl -X POST \
|
||||
|
||||
The removed HTTP+SSE `/sse` and `/message` transports return `410 Gone`.
|
||||
|
||||
Successful `server/discover` or `initialize` responses confirm connectivity, but do not validate the tool catalog.
|
||||
Use `tools/list` above to check that the client can discover tools. If it returns
|
||||
`Date cannot be represented in JSON Schema`, the server failed to generate a tool schema; changing the API key will
|
||||
not resolve that error. Update Homarr to a release containing the invitation date schema fix.
|
||||
|
||||
## Tools and resources
|
||||
|
||||
The generated catalog includes available board, app, integration, Docker, Kubernetes, media, DNS, download, and other
|
||||
Homarr procedures. Queries are read-only; mutations change state. The exact catalog depends on the release and current
|
||||
user permissions, so inspect `tools/list` or the table in Homarr instead of relying on a static list.
|
||||
|
||||
The `invite_createInvite` tool accepts `expirationDate` as an ISO 8601 timestamp with a timezone, such as
|
||||
`2026-12-01T18:00:00Z` or `2026-12-01T19:00:00+01:00`.
|
||||
|
||||
For Custom Widgets, install the official skill and follow the preview-and-evidence workflow described in
|
||||
[Connect an agent](./custom-widgets/agent-authoring). Secret values are configured in Homarr and are never returned
|
||||
through MCP.
|
||||
|
||||
+3
-1
@@ -2572,7 +2572,9 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expirationDate": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ export const InviteCreateForm = ({ onClose }: InviteCreateFormProps) => {
|
||||
onSubmit={form.onSubmit((values) => {
|
||||
mutate(
|
||||
{
|
||||
expirationDate: new Date(values.expirationDate),
|
||||
expirationDate: new Date(values.expirationDate).toISOString(),
|
||||
},
|
||||
{
|
||||
onSuccess: (result) => {
|
||||
|
||||
@@ -109,6 +109,7 @@ export function extractMcpToolsFromProcedures<TRoot extends AnyRootTypes, TRecor
|
||||
inputValidator,
|
||||
inputSchema: normalizeJsonSchema(
|
||||
z.toJSONSchema(inputValidator, {
|
||||
io: "input",
|
||||
unrepresentable: "any",
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -56,7 +56,7 @@ export const inviteRouter = createTRPCRouter({
|
||||
.requiresPermission("admin")
|
||||
.input(
|
||||
z.object({
|
||||
expirationDate: z.date(),
|
||||
expirationDate: z.iso.datetime({ offset: true }),
|
||||
}),
|
||||
)
|
||||
.output(z.object({ id: z.string(), token: z.string() }))
|
||||
@@ -80,7 +80,7 @@ export const inviteRouter = createTRPCRouter({
|
||||
|
||||
await ctx.db.insert(invites).values({
|
||||
id,
|
||||
expirationDate: input.expirationDate,
|
||||
expirationDate: new Date(input.expirationDate),
|
||||
creatorId: ctx.session.user.id,
|
||||
token,
|
||||
});
|
||||
|
||||
@@ -123,7 +123,7 @@ describe("create should create a new invite expiring on the specified date with
|
||||
|
||||
// Act
|
||||
const result = await caller.createInvite({
|
||||
expirationDate,
|
||||
expirationDate: expirationDate.toISOString(),
|
||||
});
|
||||
|
||||
// Assert
|
||||
|
||||
Reference in new issue
Block a user