Skip to content
Open
47 changes: 27 additions & 20 deletions apps/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,36 +1,43 @@
FROM node:20-slim
FROM oven/bun:1-slim AS builder

# Update dependencies
RUN apt-get update
WORKDIR /app

# Install dependencies
RUN apt-get install -y \
# Copy the monorepo source code
COPY . .

# Install dependencies and build
RUN bun install
RUN bun run build

FROM oven/bun:1-slim AS runner
WORKDIR /app

# Install system dependencies that might be needed by MCP servers
RUN apt-get update && apt-get install -y \
curl \
git \
python3-pip \
pipx
python3-venv \
pipx \
&& rm -rf /var/lib/apt/lists/*

# Used by many MCP servers
# Install uv for Python MCP servers using pipx
RUN pipx install uv

# Add pipx bin directory to PATH so uvx is available
ENV PATH="/root/.local/bin:${PATH}"

# Create director directory for volume mounting
# Create director directory
RUN mkdir -p /root/.director

# Install Director CLI globally
RUN npm install -g @director.run/cli@latest
# Copy built files and dependencies from builder
COPY --from=builder /app /app

# Set default port
ENV GATEWAY_PORT=8080

# Expose the gateway port
EXPOSE ${GATEWAY_PORT}

# Create a simple healthcheck
# HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
# CMD curl -f http://localhost:${GATEWAY_PORT}/health || exit 1
# Create a wrapper script for the director executable
RUN echo '#!/bin/sh' > /usr/local/bin/director && \
echo 'exec bun run /app/apps/cli/bin/cli.ts "$@"' >> /usr/local/bin/director && \
chmod +x /usr/local/bin/director

# Run director serve
CMD ["sh", "-c", "director serve"]
# Run the gateway server
CMD ["bun", "run", "/app/apps/gateway/bin/server.ts"]
8 changes: 8 additions & 0 deletions apps/gateway/src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ export const auth = betterAuth({
databaseHooks: {
user: {
create: {
before: async (user) => {
if (env.DISABLE_SIGNUPS) {
throw new Error("Signups are disabled on this instance");
}
return {
data: user,
};
},
after: async (user) => {
// Create a default API key for the new user and store encrypted
try {
Expand Down
4 changes: 4 additions & 0 deletions apps/gateway/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ export const env = createEnv({
.string()
.default("false")
.transform((s) => s === "true"),
DISABLE_SIGNUPS: z
.string()
.default("false")
.transform((s) => s === "true"),
// API key rate limiting configuration
API_KEY_RATE_LIMIT_WINDOW_SECONDS: z
.string()
Expand Down
7 changes: 7 additions & 0 deletions apps/gateway/src/routers/trpc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ export function createAppRouter() {
store: createPlaybookStoreRouter(),
tools: createToolsRouter(),
settings: createSettingsRouter(),
authCheck: publicProcedure.query(({ ctx }) => {
const context = ctx as GatewayContext;
return { userId: context.userId, headers: "Check console" };
}),
});
}

Expand All @@ -75,6 +79,9 @@ export function createTRPCExpressMiddleware({
headers: req.headers as Record<string, string>,
});

console.log("TRPC createContext req.headers:", req.headers);
console.log("TRPC createContext session:", session);

if (session) {
userId = session.user.id;
// Get user status from the session user object
Expand Down
21 changes: 12 additions & 9 deletions packages/utilities/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ const LOG_ERROR_STACK = process.env.LOG_ERROR_STACK === "true";

export type Logger = pino.Logger;

const stream = LOG_PRETTY
? pinoPretty({
colorize: true,
translateTime: "HH:MM:ss",
ignore: "pid,hostname",
destination: 2,
// uncomment to hide json objects for any level other than trace or debug
// hideObject: !["trace", "debug"].includes(LOG_LEVEL.toLowerCase()),
})
: pino.destination(2);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For CLI applications, using asynchronous logging can lead to lost log messages if the process exits unexpectedly or crashes before the internal buffer is flushed. Since this logger is used in a CLI context (e.g., MCP stdio transport), it is highly recommended to configure pino.destination to write synchronously by setting sync: true.

Suggested change
: pino.destination(2);
: pino.destination({ dest: 2, sync: true });


const logger = pino(
{
level: LOG_LEVEL.toLowerCase(),
Expand Down Expand Up @@ -39,15 +50,7 @@ const logger = pino(
},
},
},
LOG_PRETTY
? pinoPretty({
colorize: true,
translateTime: "HH:MM:ss",
ignore: "pid,hostname",
// uncomment to hide json objects for any level other than trace or debug
// hideObject: !["trace", "debug"].includes(LOG_LEVEL.toLowerCase()),
})
: undefined,
stream
);

export const getLogger = (name: string): Logger => logger.child({ name });