Skip to content

Commit c1d3341

Browse files
Merge branch 'master' into feature/edta-event-def-suggestions
2 parents d9e7faf + b64985b commit c1d3341

54 files changed

Lines changed: 1912 additions & 387 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

UPGRADING.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,9 @@ After upgrading:
1818
matched only `test` now also matches `Test` and `TEST`. API clients relying on exact-case matching
1919
via paginated endpoints will see additional results.
2020

21+
## Java API Changes
22+
23+
| File/method | Description |
24+
|---------------------------------------------------------------------------|-------------|
25+
| `org.graylog2.contentpacks.facades.EntityWithExcerptFacade#resolveGrants` | removed |
26+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
type = "f"
2+
message = "Fix false `Message failed to process` errors when a pipeline rule or extractor assigns a string `timestamp` field in ISO-8601 format. Such timestamps are now parsed leniently instead of being recorded as a processing failure."
3+
4+
issues = ["26025"]
5+
pulls = ["26269"]

changelog/unreleased/pr-26008.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
type = "fixed" # One of: a(dded), c(hanged), d(eprecated), r(emoved), f(ixed), s(ecurity)
2+
message = "Fix MCP server 500 error on unknown client capability fields"
3+
4+
issues = ["25956"]
5+
pulls = ["26008"]

changelog/unreleased/pr-26244.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
type = "f"
2+
message = "Fix Inputs Metrics telemetry not being reported."
3+
4+
pulls = ["26244"]

graylog2-server/src/main/java/org/graylog/events/contentpack/facade/EventDefinitionFacade.java

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,8 @@
3131
import org.graylog.events.processor.EventDefinitionDto;
3232
import org.graylog.events.processor.EventDefinitionHandler;
3333
import org.graylog.events.processor.EventProcessorExecutionJob;
34-
import org.graylog.grn.GRNTypes;
3534
import org.graylog.scheduler.DBJobDefinitionService;
3635
import org.graylog.scheduler.JobDefinitionDto;
37-
import org.graylog.security.GrantDTO;
38-
import org.graylog.security.shares.EntityGrantLookup;
3936
import org.graylog2.contentpacks.EntityDescriptorIds;
4037
import org.graylog2.contentpacks.facades.EntityFacade;
4138
import org.graylog2.contentpacks.facades.UpdatableEntityFacade;
@@ -58,7 +55,6 @@
5855
import org.slf4j.Logger;
5956
import org.slf4j.LoggerFactory;
6057

61-
import java.util.List;
6258
import java.util.Map;
6359
import java.util.Optional;
6460
import java.util.Set;
@@ -73,23 +69,20 @@ public class EventDefinitionFacade implements EntityFacade<EventDefinitionDto>,
7369
private final DBEventDefinitionService eventDefinitionService;
7470
private final Set<PluginMetaData> pluginMetaData;
7571
private final UserService userService;
76-
private final EntityGrantLookup grantLookup;
7772

7873
@Inject
7974
public EventDefinitionFacade(ObjectMapper objectMapper,
8075
EventDefinitionHandler eventDefinitionHandler,
8176
Set<PluginMetaData> pluginMetaData,
8277
DBJobDefinitionService jobDefinitionService,
8378
DBEventDefinitionService eventDefinitionService,
84-
UserService userService,
85-
EntityGrantLookup grantLookup) {
79+
UserService userService) {
8680
this.objectMapper = objectMapper;
8781
this.pluginMetaData = pluginMetaData;
8882
this.eventDefinitionHandler = eventDefinitionHandler;
8983
this.jobDefinitionService = jobDefinitionService;
9084
this.eventDefinitionService = eventDefinitionService;
9185
this.userService = userService;
92-
this.grantLookup = grantLookup;
9386
}
9487

9588
@VisibleForTesting
@@ -251,11 +244,6 @@ public boolean usesScopedEntities() {
251244
return true;
252245
}
253246

254-
@Override
255-
public List<GrantDTO> resolveGrants(EventDefinitionDto nativeEntity) {
256-
return grantLookup.getGrantsForTarget(GRNTypes.EVENT_DEFINITION, nativeEntity.id());
257-
}
258-
259247
@Override
260248
public Optional<EntityPermissions> getCreatePermissions(Entity entity) {
261249
return EntityPermissions.of(RestPermissions.EVENT_DEFINITIONS_CREATE);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (C) 2020 Graylog, Inc.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the Server Side Public License, version 1,
6+
* as published by MongoDB, Inc.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* Server Side Public License for more details.
12+
*
13+
* You should have received a copy of the Server Side Public License
14+
* along with this program. If not, see
15+
* <http://www.mongodb.com/licensing/server-side-public-license>.
16+
*/
17+
package org.graylog.mcp.server;
18+
19+
import com.google.inject.BindingAnnotation;
20+
21+
import java.lang.annotation.Retention;
22+
import java.lang.annotation.Target;
23+
24+
import static java.lang.annotation.ElementType.FIELD;
25+
import static java.lang.annotation.ElementType.METHOD;
26+
import static java.lang.annotation.ElementType.PARAMETER;
27+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
28+
29+
/**
30+
* Qualifier annotation for the ObjectMapper used to deserialize MCP protocol messages.
31+
* This mapper is a plain ObjectMapper configured with FAIL_ON_UNKNOWN_PROPERTIES=false,
32+
* unlike the global Graylog ObjectMapper which adds SnakeCaseStrategy and custom modules
33+
* that interfere with the MCP SDK's own Jackson annotations.
34+
*
35+
* Workaround for <a href="https://github.com/modelcontextprotocol/java-sdk/issues/766">java-sdk#766</a>.
36+
* Remove once the SDK adds @JsonIgnoreProperties(ignoreUnknown=true) to its capability records.
37+
*/
38+
@BindingAnnotation
39+
@Target({FIELD, PARAMETER, METHOD})
40+
@Retention(RUNTIME)
41+
public @interface McpProtocolObjectMapper {
42+
}

graylog2-server/src/main/java/org/graylog/mcp/server/McpRestResource.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public class McpRestResource extends RestResource {
6464
private static final String HEADER_MCP_SESSION_ID = "Mcp-Session-Id";
6565
private static final String HEADER_MCP_PROTOCOL_VERSION = "MCP-Protocol-Version";
6666

67-
private final ObjectMapper objectMapper;
67+
private final ObjectMapper protocolObjectMapper;
6868

6969
private final McpService mcpService;
7070

@@ -73,10 +73,10 @@ public class McpRestResource extends RestResource {
7373
private final ClusterConfigService clusterConfig;
7474

7575
@Inject
76-
public McpRestResource(final ClusterConfigService clusterConfig, final McpService mcpService, final ObjectMapper objectMapper, final SecurityContext securityContext) {
76+
public McpRestResource(final ClusterConfigService clusterConfig, final McpService mcpService, @McpProtocolObjectMapper final ObjectMapper protocolObjectMapper, final SecurityContext securityContext) {
7777
this.clusterConfig = clusterConfig;
7878
this.mcpService = mcpService;
79-
this.objectMapper = objectMapper;
79+
this.protocolObjectMapper = protocolObjectMapper;
8080
this.securityContext = securityContext;
8181
}
8282

@@ -116,7 +116,7 @@ public Response post(@HeaderParam(HttpHeaders.ACCEPT) String acceptHeader,
116116
// Simple one-shot JSON reply
117117
Object id = null;
118118
try {
119-
final McpSchema.JSONRPCRequest request = objectMapper.convertValue(payload, McpSchema.JSONRPCRequest.class);
119+
final McpSchema.JSONRPCRequest request = protocolObjectMapper.convertValue(payload, McpSchema.JSONRPCRequest.class);
120120
LOG.trace("Received JSON-RPC request {}", request);
121121
id = request.id();
122122

@@ -140,7 +140,7 @@ public Response post(@HeaderParam(HttpHeaders.ACCEPT) String acceptHeader,
140140
final Optional<McpSchema.Result> result = mcpService.handle(permissionHelper, request, sessionId, protocolVersionHeader);
141141

142142
if (result.isPresent() && LOG.isTraceEnabled()) {
143-
LOG.trace("Successfully handled JSON-RPC request: {}", objectMapper.writeValueAsString(result));
143+
LOG.trace("Successfully handled JSON-RPC request: {}", protocolObjectMapper.writeValueAsString(result));
144144
}
145145
return Response.ok(new McpSchema.JSONRPCResponse("2.0", id, result.orElse(null), null))
146146
.header(HEADER_MCP_SESSION_ID, sessionId)

graylog2-server/src/main/java/org/graylog/mcp/server/McpServerModule.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*/
1717
package org.graylog.mcp.server;
1818

19+
import com.fasterxml.jackson.databind.DeserializationFeature;
20+
import com.fasterxml.jackson.databind.ObjectMapper;
1921
import org.graylog.mcp.resources.DashboardResourceProvider;
2022
import org.graylog.mcp.resources.EventDefinitionResourceProvider;
2123
import org.graylog.mcp.resources.StreamResourceProvider;
@@ -36,6 +38,12 @@
3638
public class McpServerModule extends PluginModule {
3739
@Override
3840
protected void configure() {
41+
// Workaround for https://github.com/modelcontextprotocol/java-sdk/issues/766
42+
// Remove once the SDK adds @JsonIgnoreProperties(ignoreUnknown=true) to capability records.
43+
bind(ObjectMapper.class).annotatedWith(McpProtocolObjectMapper.class)
44+
.toInstance(new ObjectMapper()
45+
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false));
46+
3947
// Initialize schema module binder (empty set by default, plugins can contribute)
4048
schemaModuleBinder();
4149

graylog2-server/src/main/java/org/graylog/mcp/server/McpService.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public class McpService {
5959
static final List<String> ALL_SUPPORTED_MCP_VERSIONS = List.of(LATEST_SUPPORTED_MCP_VERSION);
6060

6161
private final ObjectMapper objectMapper;
62+
private final ObjectMapper protocolObjectMapper;
6263
private final AuditEventSender auditEventSender;
6364
private final CustomizationConfig customizationConfig;
6465
private final GRNRegistry grnRegistry;
@@ -67,12 +68,14 @@ public class McpService {
6768

6869
@Inject
6970
protected McpService(ObjectMapper objectMapper,
71+
@McpProtocolObjectMapper ObjectMapper protocolObjectMapper,
7072
AuditEventSender auditEventSender,
7173
CustomizationConfig customizationConfig,
7274
GRNRegistry grnRegistry,
7375
Map<String, Tool<?, ?>> tools,
7476
Map<GRNType, ? extends ResourceProvider> resourceProviders) {
7577
this.objectMapper = objectMapper;
78+
this.protocolObjectMapper = protocolObjectMapper;
7679
this.auditEventSender = auditEventSender;
7780
this.customizationConfig = customizationConfig;
7881
this.grnRegistry = grnRegistry;
@@ -93,7 +96,7 @@ public Optional<McpSchema.Result> handle(PermissionHelper permissionHelper, McpS
9396

9497
switch (request.method()) {
9598
case McpSchema.METHOD_INITIALIZE -> {
96-
final McpSchema.InitializeRequest initializeRequest = objectMapper.convertValue(request.params(), new TypeReference<>() {});
99+
final McpSchema.InitializeRequest initializeRequest = protocolObjectMapper.convertValue(request.params(), new TypeReference<>() {});
97100
auditContext.put("request", initializeRequest);
98101
final McpSchema.InitializeResult result = new McpSchema.InitializeResult(
99102
// Version negotiation: https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle#version-negotiation
@@ -130,7 +133,7 @@ public Optional<McpSchema.Result> handle(PermissionHelper permissionHelper, McpS
130133
return Optional.of(result);
131134
}
132135
case McpSchema.METHOD_RESOURCES_READ -> {
133-
final McpSchema.ReadResourceRequest readResourceRequest = objectMapper.convertValue(request.params(), new TypeReference<>() {});
136+
final McpSchema.ReadResourceRequest readResourceRequest = protocolObjectMapper.convertValue(request.params(), new TypeReference<>() {});
134137
auditContext.put("request", readResourceRequest);
135138
LOG.debug("Reading resource: {}", readResourceRequest);
136139
try {
@@ -181,7 +184,7 @@ public Optional<McpSchema.Result> handle(PermissionHelper permissionHelper, McpS
181184
return Optional.of(new McpSchema.ListToolsResult(toolList, null));
182185
}
183186
case McpSchema.METHOD_TOOLS_CALL -> {
184-
final McpSchema.CallToolRequest callToolRequest = objectMapper.convertValue(request.params(), new TypeReference<>() {});
187+
final McpSchema.CallToolRequest callToolRequest = protocolObjectMapper.convertValue(request.params(), new TypeReference<>() {});
185188
auditContext.put("request", callToolRequest);
186189

187190
LOG.debug("Calling MCP tool: {}", callToolRequest);
@@ -237,7 +240,7 @@ public Optional<McpSchema.Result> handle(PermissionHelper permissionHelper, McpS
237240
}
238241
case McpSchema.METHOD_PROMPT_GET -> {
239242
// disabled for now
240-
final McpSchema.GetPromptRequest promptRequest = objectMapper.convertValue(request.params(), new TypeReference<>() {});
243+
final McpSchema.GetPromptRequest promptRequest = protocolObjectMapper.convertValue(request.params(), new TypeReference<>() {});
241244
auditContext.put("request", promptRequest);
242245
LOG.debug("Getting prompt {}", promptRequest.name());
243246
auditEventSender.failure(auditActor, AuditEventType.create(MCP_PROMPT_GET), auditContext);

graylog2-server/src/main/java/org/graylog/security/shares/EntityGrantLookup.java

Lines changed: 0 additions & 49 deletions
This file was deleted.

0 commit comments

Comments
 (0)