import { DockerHubClient } from '../registries/dockerhub.js';
import { GHCRClient } from '../registries/ghcr.js';
import { ImageManager } from '../managers/image.js';
import { z } from 'zod';
export function getRegistryTools() {
return [
{
name: 'dockerhub_search',
description: 'Search Docker Hub for images',
inputSchema: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'Search query',
},
limit: {
type: 'number',
description: 'Maximum number of results (default: 25)',
},
page: {
type: 'number',
description: 'Page number (default: 1)',
},
},
required: ['query'],
},
},
{
name: 'dockerhub_get_tags',
description: 'Get tags for a Docker Hub repository',
inputSchema: {
type: 'object',
properties: {
namespace: {
type: 'string',
description: 'Repository namespace (e.g., "library", "nginx")',
},
repository: {
type: 'string',
description: 'Repository name',
},
page: {
type: 'number',
description: 'Page number (default: 1)',
},
pageSize: {
type: 'number',
description: 'Results per page (default: 100)',
},
},
required: ['namespace', 'repository'],
},
},
{
name: 'dockerhub_authenticate',
description: 'Authenticate with Docker Hub',
inputSchema: {
type: 'object',
properties: {
username: {
type: 'string',
description: 'Docker Hub username',
},
password: {
type: 'string',
description: 'Docker Hub password or Personal Access Token',
},
},
required: ['username', 'password'],
},
},
{
name: 'dockerhub_pull',
description: 'Pull an image from Docker Hub',
inputSchema: {
type: 'object',
properties: {
image: {
type: 'string',
description: 'Image name (e.g., "nginx:latest", "library/ubuntu:20.04")',
},
username: {
type: 'string',
description: 'Docker Hub username (for private images)',
},
password: {
type: 'string',
description: 'Docker Hub password or token',
},
},
required: ['image'],
},
},
{
name: 'dockerhub_push',
description: 'Push an image to Docker Hub',
inputSchema: {
type: 'object',
properties: {
image: {
type: 'string',
description: 'Image name to push',
},
username: {
type: 'string',
description: 'Docker Hub username',
},
password: {
type: 'string',
description: 'Docker Hub password or token',
},
},
required: ['image', 'username', 'password'],
},
},
{
name: 'ghcr_authenticate',
description: 'Authenticate with GitHub Container Registry',
inputSchema: {
type: 'object',
properties: {
token: {
type: 'string',
description: 'GitHub Personal Access Token or GITHUB_TOKEN',
},
username: {
type: 'string',
description: 'GitHub username (optional, defaults to USER)',
},
},
required: ['token'],
},
},
{
name: 'ghcr_pull',
description: 'Pull an image from GitHub Container Registry',
inputSchema: {
type: 'object',
properties: {
image: {
type: 'string',
description: 'Image name (e.g., "ghcr.io/owner/repo:tag")',
},
token: {
type: 'string',
description: 'GitHub Personal Access Token',
},
},
required: ['image', 'token'],
},
},
{
name: 'ghcr_push',
description: 'Push an image to GitHub Container Registry',
inputSchema: {
type: 'object',
properties: {
image: {
type: 'string',
description: 'Image name (e.g., "ghcr.io/owner/repo:tag")',
},
token: {
type: 'string',
description: 'GitHub Personal Access Token',
},
},
required: ['image', 'token'],
},
},
];
}
export async function handleRegistryTool(
name: string,
args: any,
dockerHubClient: DockerHubClient,
ghcrClient: GHCRClient,
imageManager: ImageManager
): Promise<any> {
try {
switch (name) {
case 'dockerhub_search': {
const parsed = z
.object({
query: z.string(),
limit: z.number().optional(),
page: z.number().optional(),
})
.parse(args);
const results = await dockerHubClient.searchRepositories(parsed.query, parsed.limit, parsed.page);
return {
content: [
{
type: 'text',
text: JSON.stringify(results, null, 2),
},
],
};
}
case 'dockerhub_get_tags': {
const parsed = z
.object({
namespace: z.string(),
repository: z.string(),
page: z.number().optional(),
pageSize: z.number().optional(),
})
.parse(args);
const tags = await dockerHubClient.getRepositoryTags(
parsed.namespace,
parsed.repository,
parsed.page,
parsed.pageSize
);
return {
content: [
{
type: 'text',
text: JSON.stringify(tags, null, 2),
},
],
};
}
case 'dockerhub_authenticate': {
const parsed = z
.object({
username: z.string(),
password: z.string(),
})
.parse(args);
const token = await dockerHubClient.authenticate(parsed.username, parsed.password);
return {
content: [
{
type: 'text',
text: JSON.stringify({ message: 'Authenticated successfully', token: token.substring(0, 10) + '...' }, null, 2),
},
],
};
}
case 'dockerhub_pull': {
const parsed = z
.object({
image: z.string(),
username: z.string().optional(),
password: z.string().optional(),
})
.parse(args);
const authconfig = parsed.username && parsed.password
? {
username: parsed.username,
password: parsed.password,
}
: undefined;
const stream = await imageManager.pullImage(parsed.image, { authconfig });
const chunks: Buffer[] = [];
for await (const chunk of stream) {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
}
return {
content: [
{
type: 'text',
text: JSON.stringify({ message: 'Image pulled successfully' }, null, 2),
},
],
};
}
case 'dockerhub_push': {
const parsed = z
.object({
image: z.string(),
username: z.string(),
password: z.string(),
})
.parse(args);
const authconfig = {
username: parsed.username,
password: parsed.password,
};
const stream = await imageManager.pushImage(parsed.image, { authconfig });
const chunks: Buffer[] = [];
for await (const chunk of stream) {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
}
return {
content: [
{
type: 'text',
text: JSON.stringify({ message: 'Image pushed successfully' }, null, 2),
},
],
};
}
case 'ghcr_authenticate': {
const parsed = z
.object({
token: z.string(),
username: z.string().optional(),
})
.parse(args);
await ghcrClient.authenticate(parsed.token, parsed.username);
return {
content: [
{
type: 'text',
text: JSON.stringify({ message: 'Authenticated with GHCR successfully' }, null, 2),
},
],
};
}
case 'ghcr_pull': {
const parsed = z
.object({
image: z.string(),
token: z.string(),
})
.parse(args);
await ghcrClient.authenticate(parsed.token);
const authconfig = ghcrClient.getAuthConfig();
const stream = await imageManager.pullImage(parsed.image, { authconfig });
const chunks: Buffer[] = [];
for await (const chunk of stream) {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
}
return {
content: [
{
type: 'text',
text: JSON.stringify({ message: 'Image pulled from GHCR successfully' }, null, 2),
},
],
};
}
case 'ghcr_push': {
const parsed = z
.object({
image: z.string(),
token: z.string(),
})
.parse(args);
await ghcrClient.authenticate(parsed.token);
const authconfig = ghcrClient.getAuthConfig();
if (!authconfig) {
throw new Error('Failed to get GHCR auth config');
}
const stream = await imageManager.pushImage(parsed.image, { authconfig });
const chunks: Buffer[] = [];
for await (const chunk of stream) {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
}
return {
content: [
{
type: 'text',
text: JSON.stringify({ message: 'Image pushed to GHCR successfully' }, null, 2),
},
],
};
}
default:
return null;
}
} catch (error: any) {
if (error.message?.includes('Unknown tool')) {
return null;
}
throw error;
}
}