diff --git a/README.md b/README.md index a5e63b8..03ecbe0 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,20 @@ Learn more and get started here: - Other optional parameters for specific repository configurations - Returns: Created repository details -5. `list_repositories` +6. `create_federated_repository` + - Create a new federated repository in Artifactory that replicates artifacts between multiple other federated repositories + - Inputs: + - `key` (string): Repository key + - `rclass` (string): Repository class (must be "federated") + - `packageType` (string): Package type of the repository + - `members` (optional array): List of federated members with URL, credentials, and configuration + - `description` (optional string): Repository description + - `projectKey` (optional string): Project key to assign the repository to + - `environments` (optional string[]): Environments to assign the repository to + - Other optional parameters for specific repository configurations + - Returns: Created repository details + +7. `list_repositories` - List all repositories in Artifactory with optional filtering - Inputs: - `type` (optional string): Filter repositories by type (local, remote, virtual, federated, distribution) @@ -533,10 +546,9 @@ For Claude Desktop with SSE transport: } } ``` -``` ## License -This MCP server is licensed under the Apache License 2.0. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the Apache License 2.0. For more details, please see the LICENSE.md file in the project repository. +This MCP server is licensed under the Apache License 2.0. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the Apache License 2.0. For more details, please see the LICENSE.md file in the project repository. \ No newline at end of file diff --git a/schemas/repositories.ts b/schemas/repositories.ts index e4d52a8..6a92922 100644 --- a/schemas/repositories.ts +++ b/schemas/repositories.ts @@ -4,7 +4,8 @@ export const PackageTypeEnum = z.enum([ "bower", "cargo", "chef", "cocoapods", "composer", "conan", "cran", "debian", "docker", "Npm", "gems", "gitlfs", "go", "gradle", "helm", "ivy", "maven", "nuget", "opkg", "p2", "pub", "puppet", "pypi", "rpm", "sbt", - "swift", "terraform", "vagrant", "yum", "generic" + "swift", "terraform", "vagrant", "yum", "generic", "alpine", "conda", "helmoci", + "huggingfaceml", "ansible", "oci" ]).describe("Package type of the repository"); export const BaseRepositorySchema = z.object({ @@ -206,6 +207,51 @@ export const CreateVirtualRepoSchema = BaseRepositorySchema.extend({ primaryKeyPairRef: z.string().optional().describe("Primary GPG key pair reference"), secondaryKeyPairRef: z.string().optional().describe("Secondary GPG key pair reference") }); + +export const CreateFederatedRepoSchema = BaseRepositorySchema.extend({ + rclass: z.literal("federated").describe("The repository type"), + members: z.array(z.object({ + url: z.string().describe("Full URL to ending with the repositoryName. Typically follows pattern: {baseUrl}/artifactory/{repoKey} where repoKey matches the primary repository key"), + enabled: z.boolean().default(true).describe("Represents the active state of the federated member.") + })).optional().describe("List of federated members. Members typically have the same repository key as the primary repository but on different Artifactory instances. URL format: {baseUrl}/artifactory/{repoKey} where repoKey should match the primary repository key for consistency"), + description: z.string().optional().describe("The federated repository public description"), + proxy: z.string().optional().describe("Proxy key"), + disableProxy: z.boolean().default(false), + notes: z.string().optional().describe("Some internal notes"), + includesPattern: z.string().default("**/*").describe("Pattern to define artifacts to include"), + excludesPattern: z.string().default("").describe("Pattern to define artifacts to exclude"), + repoLayoutRef: z.string().default("maven-2-default").describe("Repository layout reference"), + debianTrivialLayout: z.boolean().default(false).describe("Whether to use trivial layout for Debian repositories"), + checksumPolicyType: z.enum([ + "client-checksums", + "server-generated-checksums" + ]).default("client-checksums"), + handleReleases: z.boolean().default(true), + handleSnapshots: z.boolean().default(true), + maxUniqueSnapshots: z.number().default(0), + maxUniqueTags: z.number().default(0), + snapshotVersionBehavior: z.enum([ + "unique", + "non-unique", + "deployer" + ]).default("unique"), + suppressPomConsistencyChecks: z.boolean().default(false), + blackedOut: z.boolean().default(false), + xrayIndex: z.boolean().default(false), + propertySets: z.array(z.string()).optional(), + archiveBrowsingEnabled: z.boolean().default(false), + calculateYumMetadata: z.boolean().default(false), + yumRootDepth: z.number().default(0), + dockerApiVersion: z.string().default("V2"), + enableFileListsIndexing: z.boolean().default(false), + optionalIndexCompressionFormats: z.array(z.enum(["bz2", "lzma", "xz"])).optional(), + downloadRedirect: z.boolean().default(false), + cdnRedirect: z.boolean().default(false).describe("Applies to Artifactory Cloud Only"), + blockPushingSchema1: z.boolean().default(false), + primaryKeyPairRef: z.string().optional().describe("Primary GPG key pair reference"), + secondaryKeyPairRef: z.string().optional().describe("Secondary GPG key pair reference"), + priorityResolution: z.boolean().default(false).describe("Applies to all repository types excluding CocoaPods, Git LFS, NuGet V2, Opkg, RPM, Rust, Vagrant and VCS repositories") +}); export const JFrogPlatformReadinessSchema= z.object({ code: z.string() diff --git a/tools/repositories.ts b/tools/repositories.ts index f1c6547..32e294d 100644 --- a/tools/repositories.ts +++ b/tools/repositories.ts @@ -5,6 +5,7 @@ import { CreateLocalRepoSchema, CreateRemoteRepoSchema, CreateVirtualRepoSchema, + CreateFederatedRepoSchema, ListRepositoriesParamsSchema, JFrogRepositoryCreateResponseSchema, JFrogPlatformReadinessSchema, @@ -95,6 +96,15 @@ export async function createVirtualRepository(options: z.infer) { + const response = await jfrogRequest(`/artifactory/api/repositories/${options.key}`, { + method: "PUT", + body: options + }); + + return JFrogRepositoryCreateResponseSchema.parse(response); +} + /* End of Api Calls Section */ @@ -154,6 +164,17 @@ const createVirtualRepositoryTool = { } }; +const createFederatedRepositoryTool = { + name: "jfrog_create_federated_repository", + description: "Create a new federated repository in Artifactory that replicates artifacts between multiple other federated repositories. Note: Federated members typically use the same repository key as the primary repository but on different Artifactory instances. When specifying members, use URL format: {baseUrl}/artifactory/{repoKey} where repoKey should match the primary repository key for consistency", + inputSchema: zodToJsonSchema(CreateFederatedRepoSchema), + //outputSchema: zodToJsonSchema(JFrogRepositoryCreateResponseSchema), + handler: async (args: any) => { + const parsedArgs = CreateFederatedRepoSchema.parse(args); + return await createFederatedRepository(parsedArgs); + } +}; + const listRepositoriesTool = { name: "jfrog_list_repositories", description: "List all repositories in Artifactory with optional filtering by type, package type, and project", @@ -170,6 +191,7 @@ export const RepositoryTools =[ createLocalRepositoryTool, createRemoteRepositoryTool, createVirtualRepositoryTool, + createFederatedRepositoryTool, setFolderPropertyTool, listRepositoriesTool ];